
find를 사용하여 특정 파일을 찾은 다음 cp 및 sed와 함께 xargs를 사용하여 이러한 파일을 다른 폴더로 이동하고 이름을 바꾸고 싶습니다. 나는 이것을 루프에서 수행하는 방법을 알고 있지만 그것은 내가 찾고 있는 것이 아닙니다.
나는 시도했다:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
이것이 작동하지 않는 이유는 무엇이며 해결책은 무엇입니까?
답변1
이 시도. 는 필요하지 않으며 xargs
단지 find
, 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)')"