Combine xargs -I com sed

Combine xargs -I com sed

Quero usar find para encontrar determinados arquivos e, em seguida, usar xargs com cp e sed para mover esses arquivos para outra pasta e renomeá-los. Eu sei como fazer isso em loop, mas não é isso que estou procurando.

Tentei:

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

Por que isso não está funcionando e qual seria a solução?

Responder1

Experimente isso. Não precisa de xargs, apenas find, sede copy. Isso não mudará nenhum arquivo, masvaiimprima uma lista de comandos shell para copiar os arquivos. Então, se você gostar dos comandos que ele imprime, execute-o novamente e remova o #antes sh -xda última linha e deixe o shell executar os comandos.

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

Por que essa abordagem é melhor do que xargsneste caso? Porque este método inicia apenas 3 processos no total ( find,, sede sh) além do cpcomando necessário para cada arquivo.

Para usar xargs, o processamento de cada nome de arquivo exigiria mais processos do que o único cpcomando necessário.

É muito mais eficiente deixar a única invocação do sed gerartodosdos cpcomandos, do que invocar um novo sedprocesso para cada nome de arquivo.

Responder2

Usando GNU Parallel fica assim:

find ${FOLDER} -iname "*${SOME_STRING}*" |
  parallel cp {} '{= s/ABC/XYZ/g =}'

A construção {= =} contém uma expressão Perl que altera $_.

Uma das vantagens é que o GNU Parallel faz a coisa certa mesmo se você tiver arquivos chamados:

My brother's 12" records worth >100$.txt

ou horrores como:

touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"

informação relacionada