xargs -I를 sed와 결합

xargs -I를 sed와 결합

find를 사용하여 특정 파일을 찾은 다음 cp 및 sed와 함께 xargs를 사용하여 해당 파일을 다른 폴더로 이동하고 이름을 바꾸고 싶습니다. 나는 이것을 루프에서 수행하는 방법을 알고 있지만 그것은 내가 원하는 것이 아닙니다.

나는 시도했다:

find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')

이것이 작동하지 않는 이유는 무엇이며 해결책은 무엇입니까?

답변1

이 시도. 꼭 그럴 필요는 없고 xargs그냥 findand 입니다. 파일은 변경되지 않지만sedcopy~ 할 것이다파일 복사에 사용되는 쉘 명령 목록을 인쇄합니다. 따라서 인쇄된 명령이 마음에 들면 다시 실행하여 마지막 줄 #앞의 내용을 삭제 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, , 및 )만 시작하기 때문입니다.sedshcp

를 사용하려면 각 파일 이름을 처리하는 데 필요한 단일 명령보다 더 많은 프로세스가 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)')"

관련 정보