2012-05-09 11 views
163

Qualcuno può fornire il codice per eseguire quanto segue: Si supponga che esista una directory di file, che devono essere tutti eseguiti attraverso un programma. Il programma mostra i risultati come standard. Ho bisogno di uno script che vada in una directory, esegua il comando su ogni file e concatchi l'output in un unico grande file di output.Script di Bash per eseguire il comando su tutti i file in una directory

Ad esempio, per eseguire il comando in 1 lima:

$ cmd [option] [filename] > results.out 
+3

Mi piacerebbe aggiungere alla domanda. Può essere fatto usando xargs? ad es., 'ls | xargs cmd [opzioni] {nome file inserito automaticamente da xargs} [altri argomenti]> results.out' –

+0

Può, ma probabilmente [non vuoi usare 'ls'] (http: //mywiki.wooledge. org/ParsingLs) per guidare 'xargs'. Se 'cmd' è scritto con competenza, forse puoi semplicemente fare' cmd '. – tripleee

risposta

244

Il seguente codice bash passerà $ file di comandare in cui $ file rappresenterà ogni file in/dir

for file in /dir/* 
do 
    cmd [option] "$file" >> results.out 
done 

Esempio

[email protected] ~/foo $ touch foo.txt bar.txt baz.txt 
[email protected] ~/foo $ for i in *.txt; do echo "hello $i"; done 
hello bar.txt 
hello baz.txt 
hello foo.txt 
+13

Se nessun file esiste in'/dir/', allora il ciclo viene eseguito ancora una volta con un valore di '*' per' $ file', che potrebbe non essere desiderabile. Per evitare ciò, abilita nullglob per la durata del ciclo. Aggiungi questa riga prima del ciclo 'shopt -s nullglob' e questa riga dopo il ciclo' shopt -u nullglob #reinvia nullglob al suo normale stato di default'. –

+29

+1, E mi è costato tutta la mia collezione di sfondi. tutti dopo di me, usa le doppie quotazioni. "$ file" – Behrooz

+0

Se il file di output è lo stesso all'interno del ciclo, è molto più efficiente reindirizzare all'esterno del ciclo 'done> results.out' (e probabilmente è possibile sovrascrivere invece di aggiungere, come ho presunto qui). – tripleee

112

ne dite di questo:

find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out 
  • -maxdepth 1 argomento impedisce trovare da ricorsivamente scendere in qualsiasi sottodirectory. Se desideri che tali directory nidificate vengano elaborate, puoi ometterlo.
  • -type -f specifica che verranno elaborati solo file normali.
  • -exec cmd option {} dice per eseguire cmd con la specificata option per ogni file trovato, con il nome sostituito {}
  • \; indica la fine del comando.
  • Infine, l'uscita da tutti i singoli cmd esecuzioni viene reindirizzato a results.out

Tuttavia, se vi preoccupate per l'ordine in cui i file vengono elaborati, si potrebbe essere meglio a scrivere un ciclo. Penso che lo find elabori i file nell'ordine di inode (anche se potrei sbagliarmi), che potrebbe non essere quello che vuoi .

+1

Questo è il modo corretto di elaborare i file. L'utilizzo di un ciclo for è soggetto a errori a causa di molte ragioni. Anche l'ordinamento può essere fatto usando altri comandi come 'stat' e' sort', che ovviamente dipende da cosa sono i criteri di ordinamento. – tuxdna

+0

se volessi eseguire due comandi come dovrei collegarli dopo l'opzione '-exec'? Devo avvolgerli tra virgolette singole o qualcosa del genere? – frei

+0

'find' è sempre l'opzione migliore perché puoi filtrare per modello di nome file con l'opzione' -name' e puoi farlo in un unico comando. –

22

Sto facendo questo sul mio Raspberry Pi dalla riga di comando eseguendo:

for i in *;do omxplayer "$i";done 
1

avevo bisogno di copiare tutti i file .MD da una directory a un'altra, quindi ecco cosa ho fatto.

for i in **/*.md;do mkdir -p ../docs/"$i" && rm -r ../docs/"$i" && cp "$i" "../docs/$i" && echo "$i -> ../docs/$i"; done

che è piuttosto difficile da leggere, così lascia scomposizione.

primo cd nella directory con i file,

for i in **/*.md; per ogni file nel vostro modello

mkdir -p ../docs/"$i" rendere tale directory in una cartella documenti al di fuori della cartella contenente i file. Che crea una cartella aggiuntiva con lo stesso nome di quel file.

rm -r ../docs/"$i" rimuovere la cartella in più che si viene a creare a seguito di mkdir -p

cp "$i" "../docs/$i" Copiare il file vero e proprio

echo "$i -> ../docs/$i" Echo quello che hai fatto

; done vivere felici e contenti

1

Una rapida e sporco modo che ottiene il lavoro fatto a volte è:

Ad esempio, per trovare il numero di righe in tutti i file nella directory corrente, si può fare:

find . | xargs wc -l 
Problemi correlati