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단지 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, 및 )만 시작하기 때문입니다.shcp

를 사용하려면 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)')"

관련 정보