487개의 폴더가 있는 이라는 폴더가 있습니다 /home/user/temps
. 각 폴더에는 Thumb.png라는 파일이 있습니다.
Thumb.png라는 이름의 모든 파일을 별도의 폴더에 복사하고 원본 폴더에 따라 이름을 바꾸고 싶습니다.
답변1
여기 있어요:
for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;
편집하다:
그건 그렇고, 일반적인 통념은 이렇게 하는 것이 find
나쁜 생각이라는 것입니다. 단순히 쉘 확장을 사용하는 것이 더 안정적입니다. 또한 이것은 가설 bash
이지만 안전한 가정이라고 생각합니다 :)
편집 2:
명확성을 위해 분석하겠습니다.
# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do
# replace 'temps' with 'new_folder' in the path
# '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
new_file=${file/temps/new_folder};
# drop '/thumb' from the path
# '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
cp "$file" "${new_file/\/thumb/}";
done;
${var/Pattern/Replacement}
자세한 공사정보를 확인 하실 수 있습니다.여기.
이 줄의 따옴표는 cp
파일 이름의 공백, 줄 바꿈 등을 처리하는 데 중요합니다.
답변2
이 솔루션은 하위 디렉터리와 하위 디렉터리의 파일을 "평면화"하여 모두 하나의 큰 디렉터리에 상주하도록 합니다. 새 파일 이름은 원래 경로를 반영합니다. 예를 temps/dir/subdir/thumb.png
들어 가 됩니다 newdir/temps_dir_subdir_thumb.png
.
find temps/ -name "thumb.png" |
while IFS= read -r f do
cp -v "$f" "newdir/${f//\//_}"
done
디렉터리 temps
가 newdir
존재해야 합니다. 그리고 temps
명령은 및 의 상위 디렉터리에서 실행되어야 합니다 newdir
.
이 명령은 한 줄로 완료할 수도 있습니다.
find temps/ -name "thumb.png" | while IFS= read -r f; do cp -v "$f" "newdir/${f//\//_}"; done
;
개행 문자가 있는 세미콜론( )에 유의하세요.
예제 출력
$ find temps/ -name "thumb.png" | while IFS= read -r f; do cp -v "$f" "newdir/${f//\//_}"; done
`temps/thumb.png' -> `newdir/temps_thumb.png'
`temps/dir3/thumb.png' -> `newdir/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `newdir/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `newdir/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `newdir/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `newdir/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `newdir/temps_dir2_dir21_thumb.png'
확실하지 않은 경우 에 추가하여 echo
실행될 cp
내용을 확인하세요.
find temps/ -name "thumb.png" | while IFS= read -r f; do echo cp -v "$f" "newdir/${f//\//_}"; done
설명하다
이 작업은 다음을 사용하여 수행할 수 있습니다.매개변수 확장: ${f//\//_}
. 변수의 내용 f
(경로와 파일 이름 포함)을 가져와 각 항목 /
을 _
.
이것은 어리석은 텍스트 검색 및 교체입니다. 두 개의 서로 다른 파일이 동일한 이름으로 끝나는 경우 파일 중 하나를 덮어쓰게 됩니다.
예를 들어, 두 개의 파일 temps/dir/thumb.png
과 temps/dir_thumb.png
. 두 파일 모두 이름이 temps_dir_thumb.png
.로 변경되므로 하나의 파일이 손실됩니다. 손실되는 파일은 find
디스크에서 발견된 순서에 따라 다릅니다.
의무적인 현학적인 경고: 파일 이름에 개행 문자가 포함되어 있으면 이 명령이 심하게 충돌합니다.
답변3
oneliner 명령에서 파일을 찾고, 복사하고, 이름을 바꿀 수 있습니다.-sh 실행:
find /home/user/temps -name thumb.png \
-exec sh -c 'cp "{}" "$(basename "$(dirname "{}")")_$(basename "{}")"' \;
(추가 내용은 "
복사된 파일을 공백으로 처리하는 것입니다.)
옵션 2- with xargs
(실행하기 전에 각 명령을 인쇄할 수 있음):
find /home/user/temps -name thumb.png \
| xargs -I {} --verbose sh -c 'cp "{}" "$(basename "$(dirname "{}")")_$(basename "{}")"'
sh -c cp "temps/thumb.png" "$(기본 이름 "$(dirname "temps/thumb.png")")_$(기본 이름 "temps/thumb.png")"
sh -c cp "temps/dir one/thumb.png" "$(basename "$(dirname "temps/dir one/thumb.png")")_$(basename "temps/dir one/thumb.png") "
sh -c cp "temps/dir two/thumb.png" "$(basename "$(dirname "temps/dir two/thumb.png")")_$(basename "temps/dir two/thumb.png") "
답변4
이 시도
mkdir /home/user/thumbs
targDir=/home/user/thumbs
cd /home/user/temps
find . -type d |
while IFS="" read -r dir ; do
if [[ -f "${dir}"/thumb.png ]] ; then
echo mv -i "${dir}/thumb.png" "${targDir}/${dir}_thumb.png"
fi
done
편집하다
디렉터리 이름에 공백 문자가 포함된 경우를 대비해 따옴표를 추가했습니다.
나도 이렇게 바꿨어.오직실행할 명령을 인쇄합니다. 스크립트의 출력을 확인하여 모든 파일/경로 이름이 올바른지 확인하십시오. 실행하려는 명령에 문제가 없다고 확신하면 해당 명령을 삭제하십시오 echo
.