다음과 같은 파일 구조가 있습니다.
raw:
F1:
file1.pdf
F2:
file2.pdf
(...)
pdf:
(...)
폴더당 항상 하나의 PDF 파일만 있으며 파일/폴더 이름은 임의로 지정할 수 있습니다.
raw
디렉토리의 모든 pdf 파일을 pdf 디렉토리로 복사하고 해당 파일 이름을 루트 폴더 이름으로 바꾸고 싶습니다 . 위 예의 경우 결과는 다음과 같습니다.
raw:
F1:
file1.pdf
F2:
file2.pdf
(...)
pdf:
F1.pdf
F2.pdf
(...)
와일드카드 복사에 대해 읽었지만 파일을 복사하려면 두 개의 중첩된 와일드카드를 사용해야 하기 때문에 이는 문제가 있는 것 같습니다. 따라서 이것은 분명히 작동하지 않습니다.
cp raw/*/*.pdf pdf/*.pdf
이 문제를 해결할 수 있는 방법이 있습니까? 아니면 내 폴더를 반복하고 정규식을 사용하여 경로를 분할해야 합니까?
답변1
복사에 와일드카드를 사용할 수 있으며 괜찮습니다. 그러나 파일을 복사하는 것이 아니라 파일 이름을 바꿔야 합니다. 즉, 각 파일에 새 이름을 할당해야 하므로 루프가 불가피합니다. 기껏해야 루핑을 수행하는 도구를 사용할 수 있습니다.
perl-rename
( renamed
Debian 기반 시스템에서 호출) 있는 경우 다음을 수행할 수 있습니다.
$ rename -n 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
raw/F1/file1.pdf -> pdf/F1.pdf
raw/F2/file2.pdf -> pdf/F2.pdf
.pdf
이렇게 하면 이 작업을 수행하는 대신 로 끝나는 모든 파일 이름을 찾을 raw
수 있습니다 .pdf
. 따라서 만족스러우면 실제로 파일 이름을 바꾸지 않고 해당 명령을 실행하십시오.pdf/
-n
-n
rename 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
또는 쉘 루프를 사용할 수 있습니다.
for f in raw/*/*pdf; do
new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f");
echo "mv -- $f $new";
done
mv raw/F1/file1.pdf pdf/F1.pdf
mv raw/F2/file2.pdf pdf/F2.pdf
다시 한 번, 작동하는 것에 만족하면 에코를 제거하여 실제로 파일 이름을 바꿉니다.
for f in raw/*/*pdf; do
new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f");
mv -- "$f" "$new";
done
중요한: 두 솔루션 모두 디렉터리당 파일이 하나만 있다고 가정하므로 충돌이 발생하지 않습니다. 동일한 하위 디렉터리에 있는 모든 파일은 동일한 이름을 갖기 때문에 추가 파일이 제거됩니다.
-i
각 해당 도구의 옵션( mv
an )을 사용해 보면 rename
동일한 이름의 파일을 덮어쓰기 전에 확인 메시지를 표시하게 됩니다. 이렇게 하면 해결책이 만들어집니다.
rename -i 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
그리고
for f in raw/*/*pdf; do
new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f");
mv -i -- "$f" "$new";
done
답변2
중첩 루프를 사용하십시오.
shopt -s nullglob # To prevent failures if there's no pdf in a dir.
for dir in raw/* ; do
for pdf in "$dir"/*.pdf ; do
cp -- "$pdf" pdf/"${dir#raw/}".pdf # Remove the "raw/" part
done
done
또는 파일을 반복하고 매개변수 확장을 두 번 적용하여 대상 이름을 생성합니다.
for pdf in raw/*/*.pdf ; do
target=${pdf#raw/} # Remove the "raw/" part
target=${target%/*} # Remove the filename
cp -- "$pdf" pdf/"$target".pdf
done
답변3
그리고 zsh
:
autoload -Uz zmv # best in ~/.zshrc
zmv -C 'raw/(*)/*.pdf' 'pdf/$1.pdf'