Como passar uma lista de nomes de arquivos para xargs depois de verificar se o arquivo existe?

3

Eu tenho um comando ( command1 ) que retorna uma lista de nomes de arquivos como abaixo

/consumer/a.txt
/consumer/b.txt
/consumer/doesnotexist.txt

Quando canalizar a saída como command1 | xargs command2 command2 lançará exceção se um dos arquivos não existir.

Como faço para remover arquivos inexistentes antes de canalizá-los para command2 ? Eu estou esperando algo nas linhas de

command1 | xargs remove_nonexistant_files | xargs command2

command2 deve receber

/consumer/a.txt
/consumer/b.txt

como entrada.

    
por Sathish 29.10.2018 / 21:58

2 respostas

2
command1 |
xargs sh -c 'for p do [ -f "$p" ] && printf "%s\n" "$p"; done' sh |
xargs command 2

O bit extra no meio é uma outra invocação xargs de um script curto que basicamente apenas faz um loop sobre seus argumentos de linha de comando e imprime os nomes de caminho que correspondem aos arquivos regulares existentes (ou links simbólicos para arquivos regulares). Esses nomes de caminho existentes são então passados para a última parte do pipeline.

Isso pressupõe que todos os nomes de caminho estão livres de novas linhas, espaços e tabulações incorporadas.

    
por 29.10.2018 / 22:06
0

Assumindo que command1 produza a lista no formato esperado por xargs , você pode definir:

existing_plain_readable_files_only() {
  perl -le "for (@ARGV) {
    if (-f && -r) {s/'/'\\''/g; print qq('\$_')}
  }" -- "$@"
}

E use-o como:

command1 | xargs existing_plain_readable_files_only | xargs command2

Aqui, usamos o operador perl de -f apenas para arquivos regulares (não diretórios, dispositivos, pipes ...) e -r para aqueles que são legíveis pelo usuário (assumindo que command2 desejará lê-los), e usamos aspas simples, exceto para os caracteres de aspas simples que são escapados com \ .

Esse é um tipo de cotação suportado pelo xargs e pelo shell, o que significa que você também pode usar essa função para processar matrizes de shell contendo listas arbitrárias de arquivos:

eval "array2=($(existing_plain_readable_files_only "${array1[@]}"))"

(aqui assumindo ksh93 , zsh , bash , mksh ou yash shells).

    
por 29.10.2018 / 23:18

Tags