kzen.dev
  • Întrebări
  • Tag-uri
  • Utilizatori
Notificări
Recompense
Înregistrare
După înregistrare, veți primi notificări despre răspunsurile și comentariile la întrebările DVS.
Logare
Dacă aveţi deja un cont, autentificaţi-vă pentru a verifica notificările noi.
Aici vor fi recompensele pentru întrebările, răspunsurile și comentariile adăugate sau modificate.
Mai mult
Sursă
Editează
 themaestro
themaestro
Question

Executa comanda pe toate fișierele într-un director

Ar putea cineva vă rugăm să furnizați codul pentru a face următoarele: Presupun că există un director de fișiere, toate de care trebuie să fi rulat printr-un program. Programul ieșiri rezultatele la ieșirea standard. Am nevoie de un script care va merge într-un director, executați comanda de pe fiecare fișier, și concat ieșire într-un fișier de ieșire.

De exemplu, pentru a rula comanda pe 1 fișier:

$ cmd [option] [filename] > results.out
254 2012-05-09T20:12:42+00:00 9
 codeforester
codeforester
Întrebarea editată 15 iulie 2019 в 10:12
Programare
scripting
bash
Solution / Answer
Andrew Logvinov
Andrew Logvinov
9 mai 2012 в 8:18
2012-05-09T20:18:24+00:00
Mai mult
Sursă
Editează
#16148262

Următoarele bash cod va trece $fișier pentru a comanda în cazul în care fișierul va reprezenta fiecare fișier în /dir

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

Exemplu

[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
Wayne Werner
Wayne Werner
Răspuns editat 24 noiembrie 2015 в 1:28
377
0
Jim Lewis
Jim Lewis
9 mai 2012 в 8:17
2012-05-09T20:17:40+00:00
Mai mult
Sursă
Editează
#16148261

Ce zici de asta:

find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out
  • -maxdepth 1 argument previne găsi din recursiv descendent în orice subdirectoare. (Dacă vrei, cum ar imbricate directoare pentru a obține prelucrate, puteți omite acest lucru.)
  • -tip -f specifică faptul că doar simplu fișierele vor fi prelucrate.
  • -exec cmd opțiunea {} spune-l pentru a rula " cmd "specificate" opțiunea " pentru fiecare fișier găsit, cu numele substituit pentru {}
  • \; denotă sfârșitul comenzii.
  • În cele din urmă, la ieșire din toate individuală " cmd " executii este redirecționat către rezultatele.out

Cu toate acestea, dacă vă pasă de ordinea în care fișierele sunt prelucrate, ai ar fi mai bine scris-o buclă. Cred că "găsi" procese fișierele în inode ordine (deși am putea fi greșit), care nu poate fi ceea ce vrei.

Carles Alcolea
Carles Alcolea
Răspuns editat 18 august 2017 в 11:26
159
0
 robgraves
robgraves
19 mai 2016 в 9:03
2016-05-19T21:03:33+00:00
Mai mult
Sursă
Editează
#16148264

Am'm a face acest lucru pe raspberry pi din linia de comandă de funcționare:

for i in *;do omxplayer "$i";done
47
0
Eric Wooley
Eric Wooley
1 noiembrie 2017 в 9:57
2017-11-01T21:57:44+00:00
Mai mult
Sursă
Editează
#16148265

Nu este nevoie pentru a copia toate .md fișiere dintr-un director în altul, deci, aici este ceea ce am făcut.

pentru că în **/*.md;face mkdir -p ../docs/"$i" && rm -r ../docs/"$i" && cp "$i" "../docs/$i" && echo "$i -> ../docs/$i"; done

Care este destul de greu de citit, deci, vă permite să-l rupe în jos.

primul cd în directorul cu fișiere,

`pentru că în */.md; pentru fiecare fișier în model

mkdir -p ../docs/"$i"face acel director într-un docs afara de folderul care conține fișierele. Care creează un plus de dosar cu același nume ca fișierul.

rm -r ../docs/"$i" elimina extra folder care este creat ca urmare a mkdir -p

cp "$i" "../docs/$i" Copia fișierul în sine

echo "$i -> ../docs/$i" Echo ce ai facut

`; făcut pentru a Trăi până la adânci bătrâneți

2
0
 Rahul
Rahul
9 februarie 2018 в 6:03
2018-02-09T18:03:14+00:00
Mai mult
Sursă
Editează
#16148266

Unul rapid și murdar modul în care își face treaba, uneori, este:

find directory/ | xargs  Command 

De exemplu, pentru a găsi numărul de linii în toate fișierele din directorul curent, puteți face:

find . | xargs wc -l
2
0
 Chetabahana
Chetabahana
11 iunie 2019 в 12:35
2019-06-11T12:35:49+00:00
Mai mult
Sursă
Editează
#16148269

Maxdepth

Am constatat că funcționează bine cu Jim Lewis's a răspunde trebuie doar să adăugați un pic de genul asta:

$ export DIR=/path/dir && cd $DIR && chmod -R +x *
$ find . -maxdepth 1 -type f -name '*.sh' -exec {} \; > results.out

Ordinea De Sortare

Dacă vrei să execute în ordine de sortare, se modifica astfel:

$ export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -maxdepth 2 -type f -name '*.sh' | sort | bash > results.out

Doar un exemplu, acest lucru va executa cu următoarele ordine:

bash: 1: ./assets/main.sh
bash: 2: ./builder/clean.sh
bash: 3: ./builder/concept/compose.sh
bash: 4: ./builder/concept/market.sh
bash: 5: ./builder/concept/services.sh
bash: 6: ./builder/curl.sh
bash: 7: ./builder/identity.sh
bash: 8: ./concept/compose.sh
bash: 9: ./concept/market.sh
bash: 10: ./concept/services.sh
bash: 11: ./product/compose.sh
bash: 12: ./product/market.sh
bash: 13: ./product/services.sh
bash: 14: ./xferlog.sh

Adâncime Nelimitat

Dacă vrei să execute în adâncime nelimitat de anumite condiții, puteți folosi acest lucru:

export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -type f -name '*.sh' | sort | bash > results.out

apoi a pus pe partea de sus a fiecărei fișiere în copil directoare de genul asta:

#!/bin/bash
[[ "$(dirname `pwd`)" == $DIR ]] && echo "Executing `realpath $0`.." || return

și undeva în corpul de părinte fișier:

if <a condition is matched>
then
    #execute child files
    export DIR=`pwd`
fi
 Chetabahana
Chetabahana
Răspuns editat 13 iunie 2019 в 9:44
1
0
 Inian
Inian
16 aprilie 2019 в 7:32
2019-04-16T07:32:25+00:00
Mai mult
Sursă
Editează
#16148267

Acceptat/high-au votat răspunsuri sunt mari, dar ele sunt lipsite de câteva nitty-gritty detalii. Acest post se referă la cazurile pe cum să se ocupe mai bine atunci când shell calea-nume de expansiune (glob) nu reușește, atunci când numele fișierelor conțin liniile/simboluri de bord și se deplasează comanda de ieșire de re-direcția de ieșire din buclă de-atunci când scrie rezultatele într-un fișier.

Atunci când rulează shell glob de expansiune folosind * există o posibilitate de extindere a eșua în cazul în care există no fișierele prezente în directorul și ne-a extins glob șir va fi trecut la comandă pentru a fi rulat, care ar putea avea rezultate nedorite. Anii bash shell oferă un extins shell opțiune pentru acest lucru, folosindnullglob`. Deci bucla, practic, devine, după cum urmează în directorul care conține fișierele dvs.

 shopt -s nullglob

 for file in ./*; do
     cmdToRun [option] -- "$file"
 done

Acest lucru vă permite să în condiții de siguranță de ieșire din buclă atunci când expresia ./* nu orice fișiere ( dacă directorul este gol)

sau într-un mod compatibil POSIX (`nullglob "este" bash specifice)

 for file in ./*; do
     [ -f "$file" ] || continue
     cmdToRun [option] -- "$file"
 done

Acest lucru vă permite să mergeți în interiorul buclei, atunci când expresia nu o dată și starea [ -f "$file" ] verifica dacă onu-a extins string ./* este un nume de fișier valid în acel director, care nu't fi. Deci, în această stare de eșec, folosind "continue" ne cv-ul înapoi la "pentru" buclă care a câștigat't rula ulterior.

Rețineți, de asemenea, utilizarea de -- doar înainte de a trece numele fișierului argument. Acest lucru este necesar pentru că, după cum sa menționat anterior, coajă de nume de fișiere poate conține linii oriunde in nume de fișier. Unele comenzi shell interpreta și de a le trata ca o comandă opțiune atunci când numele sunt nu citat în mod corespunzător și execută comanda gândesc că dacă steagul este furnizat.

La -- semnale de la sfârșitul de opțiuni de linie de comandă în acest caz, ceea ce înseamnă, comanda ar trebui't analiza orice siruri de caractere dincolo de acest punct ca comanda steaguri, ci doar ca nume de fișiere.


Dublu-cu referire la nume de fișiere în mod corespunzător rezolvă cazurile când numele conține glob de caractere sau alb-spații. Dar *nix nume de fișiere pot, de asemenea, conține liniile noi în ele. Deci, avem de-limită de nume de fișiere cu singurul personaj care nu poate fi parte a unui nume de fișier valid - la byte null (\0). Din bash folosește intern " C " stil de siruri de caractere în care null bytes sunt folosite pentru a indica sfârșitul șirului, este candidatul potrivit pentru acest lucru.

Deci, folosind "printf" opțiune de shell pentru a delimita fișierele cu această NULL byte folosind -d posibilitatea de a "citi" comanda, putem face mai jos

( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
    cmdToRun [option] -- "$file"
done

Anii nullglob si "printf" sunt înfășurate în jurul (..) ceea ce înseamnă că sunt, practic, a alerga într-un sub-shell (copil shell), pentru a evita nullglob opțiunea de a reflecta asupra părinte shell, odată ce comanda ieșirile. La -d &#39;&#39; opțiunea de a "citi" comanda nu este POSIX compliant, deci are nevoie de un bash shell pentru ca acest lucru să fie făcut. Folosind "găsi" comanda acest lucru poate fi făcut ca

while IFS= read -r -d '' file; do
    cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0)

Pentru a "găsi" implementări că don't de sprijin `-print0 (altele decât GNU și FreeBSD implementari), acest lucru poate fi emulat folosind "printf"

find . -maxdepth 1 -type f -exec printf '%s\0' {} \; | xargs -0 cmdToRun [option] --

Un alt fix important este de a muta re-direcția de ieșire din buclă de-a reduce un număr mare de fișiere I/O. atunci Când este utilizat în interiorul buclei, shell-ul trebuie să execute sistem de apeluri de două ori pentru fiecare iterație a pentru-buclă, o dată pentru deschiderea și o dată pentru închiderea descriptorului de fișier asociat cu fișierul. Acest lucru va deveni o sticla de gât pe performanță pentru a rula mare de iterații. Recomandat sugestie ar fi să-l mute în afara buclei.

Extinderea codul de mai sus cu aceasta stabilește, ai putea face

( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
    cmdToRun [option] -- "$file"
done > results.out

care va pune practic conținutul de comanda pentru fiecare iterație a fișierului de intrare la stdout și atunci când bucla se termină, deschideți fișierul țintă o dată pentru a scrie conținutul stdout și salvarea. Echivalentul "găsi" versiune a aceluiași ar fi

while IFS= read -r -d '' file; do
    cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0) > results.out
 Inian
Inian
Răspuns editat 25 octombrie 2019 в 3:53
1
0
 yovie
yovie
16 aprilie 2019 в 7:37
2019-04-16T07:37:34+00:00
Mai mult
Sursă
Editează
#16148268

cred că soluția este simplă: sh /dir/* > ./result.txt

1
0
 tuxdna
tuxdna
25 decembrie 2013 в 8:13
2013-12-25T08:13:17+00:00
Mai mult
Sursă
Editează
#16148263

Bazat pe @Jim Lewis's de abordare:

Aici este o soluție rapidă, folosind "găsi" și, de asemenea, sortarea fișierelor după data lor de modificare:

$ find  directory/ -maxdepth 1 -type f -print0 | \
  xargs -r0 stat -c "%y %n" | \
  sort | cut -d' ' -f4- | \
  xargs -d "\n" -I{} cmd -op1 {} 

Pentru sortare se vedea:

http://www.commandlinefu.com/commands/view/5720/find-files-and-list-them-sorted-by-modification-time

1
0
Adăugati o întrebare
Categorii
Toate
Tehnologii
Cultură
Viață / Artă
Stiință
Profesii
Afaceri
Utilizatori
Toate
Nou
Populare
1
ALEX EPRST
Înregistrat 14 ore în urmă
2
Daniel Gogov
Înregistrat 1 săptămână în urmă
3
工藤 芳則
Înregistrat 2 săptămâni în urmă
4
Ирина Беляева
Înregistrat 2 săptămâni în urmă
5
Darya Arsenyeva
Înregistrat 3 săptămâni în urmă
DE
ES
FR
ID
IT
JA
KO
NL
NO
PT
RO
RU
TR
ZH
© kzen.dev 2023
Sursă
stackoverflow.com
în cadrul licenței cc by-sa 3.0 cu atribuire