Para iterar uma lista de nomes de arquivos com um nome por linha, você tem várias possibilidades:
-
Use a substituição de comando para trabalhar o arquivo em uma lista de nomes de arquivos dentro do shell. Você precisa tomar precauções, porque você não pode colocar a substituição do comando entre aspas duplas, pois o resultado da substituição do comando precisa ser dividido em palavras. Você precisa desativar globbing e definir IFS
para dividir apenas palavras em novas linhas.
set -f; IFS='
'
scp -- $(…) remote.example.com:
-
Use o read
interno para processar os nomes dos arquivos em um loop. Novamente, você precisa ser cuidadoso, porque read
trata as barras invertidas e $IFS
caracteres especialmente.
… | while IFS= read -r x; do scp -- "$x" remote.example.com: done
-
Você pode usar o GNU xargs, mas precisa trabalhar com cuidado, porque o xargs espera sua entrada em um formato com cotação estranha. Você deve passar a opção -d '\n'
para selecionar explicitamente novas linhas como o separador de entrada e desativar o comportamento especial de espaço em branco e \'"
.
… | xargs -d '\n' -I {} scp {} remote.example.com:
A única vantagem de xargs
é que ele pode agrupar vários argumentos em uma chamada até o limite de comprimento da linha de comando, mas isso só funciona se os argumentos forem passados por último para o comando. Você pode conseguir isso através de uma chamada intermediária para sh
, mas raramente vale a pena.
… | xargs -d '\n' sh -c 'scp -- "$@" "$0"' remote.example.com:
-
Uma maneira mais fácil de usar xargs
é obter uma lista separada por nulo em vez de uma separada por nova linha. Isso requer a opção -0
, que é suportada pelo GNU xargs e também pelo * BSD recente. Como acima, empurrar os argumentos para uma posição não final requer um pouco de trabalho.
… | tr '\n' 'set -f; IFS='
'
scp -- $(grep -l CONTENT_REGEXP -- $(cat /path/to/filenames.list)) \
remote.example.com:
' | xargs -0 sh -c 'scp -- "$@" "$0"' remote.example.com:
A parte …
seria grep NAME_REGEXP /path/to/filenames.list
se você quisesse filtrar os nomes dos arquivos com uma expressão regular. Se você quisesse filtrar o conteúdo do arquivo, use uma das técnicas acima para alimentar os nomes dos arquivos para grep
, por exemplo,
grep NAME_REGEXP /path/to/filenames.list |
rsync -a --files-from - . remote.example.com:
Outra possibilidade que ignora as dificuldades do shell é usar a opção rsync
e sua --files-from
. Supondo que os nomes dos arquivos sejam todos relativos ao diretório atual:
set -f; IFS='
'
scp -- $(…) remote.example.com: