Am crezut că acest lucru ar fi simplu – dar se dovedește mai complex decât mă așteptam.
Vreau să iterez prin toate fișierele unui anumit tip dintr-un director, așa că scriu acest lucru:
#!/bin/bash for fname in *.zip ; do echo current file is ${fname} done 
Acest lucru funcționează atâta timp cât există cel puțin un fișier care se potrivește în director. Cu toate acestea, dacă nu există fișiere potrivite, obțin acest lucru:
current file is *.zip 
Am încercat apoi:
#!/bin/bash FILES=`ls *.zip` for fname in "${FILES}" ; do echo current file is ${fname} done 
În timp ce corpul buclei nu se execută atunci când nu există fișiere, primesc o eroare de la ls:
ls: *.zip: No such file or directory 
Cum scriu un buclă care nu gestionează în mod curat niciun fișier care se potrivește?
Comentarii
Răspunde
 În bash, puteți seta opțiunea nullglob astfel încât un model care nimeni nu „dispare”, mai degrabă decât tratat ca un șir literal: 
shopt -s nullglob for fname in *.zip ; do echo "current file is ${fname}" done 
 În scriptul shell POSIX, trebuie doar să verificați dacă fname există (și în același timp cu [ -f ], verificați dacă este un fișier obișnuit (sau link simbolic către un fișier obișnuit) și nu alte tipuri precum directorul / fifo / dispozitiv .. .): 
for fname in *.zip; do [ -f "$fname" ] || continue printf "%s\n" "current file is $fname" done 
 Înlocuiți [ -f "$fname" ] cu [ -e "$fname" ] || [ -L "$fname ] dacă doriți să parcurgeți toate fișierele (care nu sunt ascunse) al căror nume se termină cu .zip, indiferent de tipul lor. 
 Înlocuiți *.zip cu .*.zip .zip *.zip dacă doriți să luați în considerare și fișierele ascunse al căror nume se termină cu .zip. 
Comentarii
-  
shopt -s nullglobnu a funcționat pentru eu pe Ubuntu 17.04, dar[ -f "$fname" ] || continuea funcționat bine. -  @koppor Se pare că nu folosiți ' 
bash. - +1 pentru o soluție POSIX.
 
Răspuns
set ./* #set the arg array to glob results ${2+":"} [ -e "$1" ] && #if more than one result skip the stat "$1" printf "current file is %s\n" "$@" #print the whole array at once ###or### ${2+":"} [ -e "$1" ] && #same kind of test for fname #iterate singly on $fname var for array do printf "file is %s\n" "$fname" #print each $fname for each iteration done 
Într-un comentariu aici menționați invocarea unei funcții …
file_fn() if [ -e "$1" ] || #check if first argument exists [ -L "$1" ] #or else if it is at least a broken link then for f #if so iterate on "$f" do : something w/ "$f" done else command <"${1-/dev/null}" #only fail w/ error if at least one arg fi file_fn * 
Răspuns
Utilizați găsi
export -f myshellfunc find . -mindepth 1 -maxdepth 1 -type f -name "*.zip" -exec bash -c "myshellfunc "$0"" {} \; 
 TREBUIE să exportați funcția shell cu export -f pentru ca acest lucru să funcționeze. Acum find execută bash care execută funcția dvs. de shell și rămâne doar la nivelul actual al dir. 
Comentarii
- Care se repetă prin subdirectoare și vreau să invoc o funcție bash (nu script) pentru potriviri.
 - @symcbean I ' a fost editat pentru a se limita la direcția unică și a gestiona funcțiile bash
 
Răspuns
În schimb of:
FILES=`ls *.zip` 
Încercați:
FILES=`ls * | grep *.zip` 
În acest fel, dacă ls eșuează (care este face în cazul dvs.) va grep ieșirea eșuată și va reveni ca o variabilă necompletată.
current file is <---Blank Here 
Puteți adăuga o logică la aceasta pentru a face să revină „Nu Fișier găsit „
#!/bin/bash FILES=`ls * | grep *.zip` if [[ $? == "0" ]]; then for fname in "$FILES" ; do echo current file is $fname done else echo "No Files Found" fi 
În acest fel, dacă comanda anterioară a reușit (a ieșit cu o valoare 0), atunci va imprima fișierul curent, altfel va imprima„ Nu Fișiere găsite „
Comentarii
-  I thi nk, este o idee proastă să mai adăugați un proces (
grep) decât să încercați să remediați problema utilizând un instrument mai bun (find) sau modificarea setării relevante pentru soluția curentă (cushopt -s nullglob) -  Conform comentariului OP ' în postarea lor originală 
shopt -s nullglobnu funcționează. Am încercatfindîn timp ce mi-am verificat răspunsul și nu a reușit. Cred că din cauza exportului a spus Dani. 
shopt -s nullglobînainte de a rula bucla for.FILES=ls * .zip; for fname in "${FILES}"...dar funcționează așa cum era de așteptat cufor fname in *.zip ; do....for file in *.zip, nu`ls ...`. @cuonglm ' sugestia este astfel încât*.zipsă se extindă la nimic atunci când modelul nu ' nu se potrivește cu orice fișier.lsfără argumente listează directorul curent.lstrebuie să fie în general evitat: De ce nu analizațils? ; consultați, de asemenea, linkul din partea de sus a paginii către BashGuide ' s ParsingLs articol.