find를 사용하여 특정 파일을 찾은 다음 cp 및 sed와 함께 xargs를 사용하여 해당 파일을 다른 폴더로 이동하고 이름을 바꾸고 싶습니다. 나는 이것을 루프에서 수행하는 방법을 알고 있지만 그것은 내가 원하는 것이 아닙니다.
나는 시도했다:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
이것이 작동하지 않는 이유는 무엇이며 해결책은 무엇입니까?
답변1
이 시도. 꼭 그럴 필요는 없고 xargs
그냥 find
and 입니다. 파일은 변경되지 않지만sed
copy
~ 할 것이다파일 복사에 사용되는 쉘 명령 목록을 인쇄합니다. 따라서 인쇄된 명령이 마음에 들면 다시 실행하여 마지막 줄 #
앞의 내용을 삭제 sh -x
하고 쉘이 명령을 실행하도록 할 수 있습니다.
find "${FOLDER:-.}" -iname "*${SOME_STRING:-ABC}*" |
sed "
s/^/'/ # surround filename with single quotes
s/$/'/
h # save filename in the sed hold space
s/ABC/XYZ/g # change filename
H # append to hold space (separates with newline)
g # get original and modified from hold
s/\n/ /g # replace the newline with a space
s/^/cp -i/ # make it into a copy command
" #| sh -x # optionally pipe to shell
xargs
이 접근 방식이 이 예보다 나은 이유는 무엇입니까? 이 방법은 각 파일에 필요한 명령 외에 총 3개의 프로세스( find
, , 및 )만 시작하기 때문입니다.sed
sh
cp
를 사용하려면 각 파일 이름을 처리하는 데 필요한 단일 명령보다 더 많은 프로세스가 xargs
필요합니다 .cp
sed를 한 번 호출하면 훨씬 더 효율적으로 생성됩니다.모두cp
각 파일 이름에 대해 새 sed
프로세스를 호출하는 대신 명령을 실행합니다 .
답변2
GNU Parallel을 사용하면 다음과 같습니다:
find ${FOLDER} -iname "*${SOME_STRING}*" |
parallel cp {} '{= s/ABC/XYZ/g =}'
{= =} $_에 대한 변경 사항을 포함하는 Perl 표현식을 구성합니다.
장점 중 하나는 다음 파일이 있어도 GNU Parallel이 올바른 작업을 수행한다는 것입니다.
My brother's 12" records worth >100$.txt
또는 이와 유사한 공포:
touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"