Combine xargs -I com sed

2

Eu quero usar o 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 um loop, mas não é isso que estou procurando.

Eu tentei:

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

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

    
por Vincent 07.11.2015 / 19:02

2 respostas

3

Tente isso. Não é necessário xargs , apenas find , sed e copy . Ele não irá alterar nenhum arquivo, mas irá imprimir uma lista de comandos do shell para copiar os arquivos. Então, se você gostar dos comandos que ele imprime, execute-o novamente e remova o # antes do sh -x na ú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 que xargs nesse caso? Como esse método inicia apenas o total de três processos ( find , sed e sh ) além do comando cp necessário para cada arquivo.

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

É muito mais eficiente permitir que a única chamada de sed gere todos os comandos cp , do que invocar um novo processo sed para cada nome de arquivo.

    
por 07.11.2015 / 19:26
2

Usando o GNU Parallel, é 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 The Right Thing, mesmo que você tenha 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)')"
    
por 12.11.2015 / 13:00

Tags