Come alimentare l'output di grep in scp?


1

Ho un file in cui ogni riga è un nome di file. Contenuto del file:

file1
file2
file3
...

Quindi eseguo a grep comando per ottenere un sottoinsieme dell'elenco dei nomi dei file.

Come posso alimentare l'output del grep comando in scp? Ho giocato con xargs e $() senza molto successo ...

Risposte:


2

Non c'è bisogno di usare xargs:

for file in $(grep <some-pattern> <filelist>); do scp $file <remote>; done;

Dove

  • <some-pattern> è tuo grep modello
  • <filelist> è la tua lista di file
  • <remote> è la tua estremità remota del scp comando

Il for loop itererà su ogni linea prodotta da grep e passare questo a $file, che puoi riutilizzare nei comandi eseguiti tra do e done.

Vedi anche: Guida avanzata di Bash-Scripting: - Loop


1
Non dimenticare di citare i nomi dei file (in caso di spazi).
SamK

1
Se uno qualsiasi dei nomi di file contiene spazi bianchi o caratteri globbing, questo non funzionerà.
Gilles

Supponiamo ora che ci siano migliaia di file da cercare. Che cos'è un modo efficace?
StatsSorceress

@StatsSorceress Più veloce di grep ping attraverso i file? Non riesco a pensare a nulla ora, ma la risposta di Gilles è migliore in ogni caso.
slhck

1

Per scorrere su un elenco di nomi di file con un nome per riga, hai diverse possibilità:

  • Utilizzare la sostituzione di comando per lavorare il file in un elenco di nomi di file all'interno della shell. È necessario prendere precauzioni, perché non è possibile inserire la sostituzione di comando tra virgolette, poiché il risultato della sostituzione di comando deve essere diviso in parole. Devi disattivare il globbing e impostare IFS per dividere solo le parole su newline.

    set -f; IFS='
    '
    scp -- $(…) remote.example.com:
    
  • Utilizzare il read built-in per elaborare i nomi dei file in un ciclo. Di nuovo, devi stare attento, perché read tratta backslash e $IFS personaggi appositamente.

    … | while IFS= read -r x; do scp -- "$x" remote.example.com: done
    
  • Puoi usare GNU xargs, ma devi procedere con cautela, perché xargs si aspetta il suo input in un formato stranamente quotato. Devi passare il -d '\n' opzione per selezionare esplicitamente le nuove linee come separatore di input e disattivare il comportamento speciale di spazi bianchi e \'".

    … | xargs -d '\n' -I {} scp {} remote.example.com:
    

    L'unico vantaggio di xargs è che può raggruppare più argomenti su una invocazione fino al limite della lunghezza della riga di comando, ma che funziona solo se gli argomenti vengono passati per ultimi al comando. Puoi farlo attraverso una chiamata intermedia a sh, ma raramente ne vale la pena.

    … | xargs -d '\n' sh -c 'scp -- "$@" "$0"' remote.example.com:
    
  • Un modo più semplice da usare xargs è quello di ottenere una lista separata da zero invece di una nuova riga. Ciò richiede il -0 opzione, che è supportata da GNU xargs e anche recente * BSD. Come sopra, spingere gli argomenti in una posizione non definitiva richiede un po 'di lavoro.

    … | tr '\n' '\0' | xargs -0 sh -c 'scp -- "$@" "$0"' remote.example.com:
    

Il parte sarebbe grep NAME_REGEXP /path/to/filenames.list se intendevi filtrare i nomi dei file con un'espressione regolare. Se intendevi filtrare il contenuto del file, utilizza una delle tecniche sopra riportate per inserire i nomi dei file grep, per esempio.

set -f; IFS='
'
scp -- $(grep -l CONTENT_REGEXP -- $(cat /path/to/filenames.list)) \
    remote.example.com:

Un'altra possibilità che aggira le difficoltà della shell è l'uso rsync e la sua --files-from opzione. Supponendo che i nomi dei file siano tutti relativi alla directory corrente:

grep NAME_REGEXP /path/to/filenames.list |
rsync -a --files-from - . remote.example.com:

Molto elaborato, ti darò questo! (Mi sto solo chiedendo, questo giustifica ancora il downvoting se ha funzionato per l'OP?)
slhck

@slhck Qualsiasi risposta che è sbagliata (e non intendo solo errato nel dettaglio, se fosse solo questione di aggiungere una citazione o due avrei appena modificato la tua risposta) è un obiettivo di downvoting legittimo, infatti dovrebbero essere downvoted. Una risposta che sembra giusta quando la testate su un semplice esempio, ma le interruzioni negli scenari del mondo reale sono le peggiori.
Gilles

Beh, non è "sbagliato" quando funziona, anche se potrebbe essere uno scenario semplice. Il pulsante in realtà dice: "Questa risposta non è utile", e ovviamente era utile. Sapevo che non avrebbe funzionato con nomi di file complessi, e aggiungendo il tuo commento sopra, questo è stato assolutamente chiarito. Ma sì, lasciamo perdere, non litigheremo!
slhck

Grazie per la tua risposta dettagliata, Gilles, sono sicuro che sarà utile se incontrassi nomi di file complessi.
dognar

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.