Luulin, että tämä olisi yksinkertaista – mutta se osoittautuu monimutkaisemmaksi kuin odotin.
Haluan toistaa kaikki tietyn tyyppiset tiedostot hakemistossa, joten kirjoitan tämän:
#!/bin/bash for fname in *.zip ; do echo current file is ${fname} done
Tämä toimii niin kauan kuin sitä on vähintään yksi vastaava tiedosto hakemistossa. Jos vastaavia tiedostoja ei kuitenkaan ole, saan tämän:
current file is *.zip
Yritin sitten:
#!/bin/bash FILES=`ls *.zip` for fname in "${FILES}" ; do echo current file is ${fname} done
Vaikka silmukan runko ei toteudu, kun tiedostoja ei ole, saan virheen ls: ltä:
ls: *.zip: No such file or directory
Kuinka kirjoitan silmukka, joka ei käsittele yhtään vastaavaa tiedostoa?
Kommentit
Vastaa
Kohdassa bash
voit asettaa vaihtoehdon nullglob
siten, että kuvio, joka ei vastaa mitään ”katoaa”, eikä sitä pidetä kirjaimellisena merkkijonona:
shopt -s nullglob for fname in *.zip ; do echo "current file is ${fname}" done
POSIX-komentosarjakomennossa tarkistat vain, että fname
on olemassa (ja samanaikaisesti [ -f ]
: n kanssa, tarkista, että se on tavallinen tiedosto (tai symlink tavalliseen tiedostoon) eikä muita tyyppejä, kuten hakemisto / fifo / device .. .):
for fname in *.zip; do [ -f "$fname" ] || continue printf "%s\n" "current file is $fname" done
Korvaa [ -f "$fname" ]
sanoilla [ -e "$fname" ] || [ -L "$fname ]
, jos haluat silmukata kaikki (piilotetut) tiedostot, joiden nimi päättyy .zip
, riippumatta niiden tyyppi.
Korvaa *.zip
sanoilla .*.zip .zip *.zip
, jos haluat ottaa huomioon myös piilotetut tiedostot, joiden nimi päättyy .zip
.
Kommentit
-
shopt -s nullglob
ei toimi minä Ubuntu 17.04: ssä, mutta[ -f "$fname" ] || continue
toimi hyvin. - @koppor Kuulostaa siltä, ettet tosiasiallisesti käytä '
bash
. - +1 POSIX-ratkaisulle.
Vastaa
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
Tässä kommentissa mainitset funktion kutsumisen …
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 *
vastaus
Käytä hakua
export -f myshellfunc find . -mindepth 1 -maxdepth 1 -type f -name "*.zip" -exec bash -c "myshellfunc "$0"" {} \;
Kuoritoimintosi on PITÄÄ viedä div id = ”f58dd7dd33″>
, jotta tämä toimisi. Nyt find
suorittaa bash
, joka suorittaa kuoritoiminnon, ja pysyy vain nykyisellä dir-tasolla.
Kommentit
- joka toistuu alihakemistojen kautta, ja haluan kutsua otteluille bash-toiminnon (ei komentosarjan).
- @symcbean I ' muokattu rajoittamaan yksittäisiä käskyjä ja käsittelemään bash-toimintoja
Vastaus
Sen sijaan /
FILES=`ls *.zip`
Yritä:
FILES=`ls * | grep *.zip`
Tällä tavalla, jos ls epäonnistuu (mikä se tekee tapauksessasi) se ottaa viallisen tuloksen ja palaa tyhjänä muuttujana.
current file is <---Blank Here
Voit lisätä tähän logiikkaa, jotta se palaa ”Ei” Tiedosto löydetty ”
#!/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
Jos edellinen komento onnistui (poistutaan 0-arvolla), se tulostaa nykyisen tiedoston, muuten se tulosta” Ei ” Löydetyt tiedostot ”
kommentit
- minä nk, on huono idea lisätä vielä yksi prosessi (
grep
) sen sijaan, että yrität korjata ongelman paremmalla työkalulla (find
) tai muuttamalla nykyisen ratkaisun asiaankuuluvaa asetusta (shopt -s nullglob
) - OP ' -kommentin mukaan alkuperäisessä viestissä
shopt -s nullglob
ei toimi. Yritinfind
vahvistaessani vastaukseni, ja se epäonnistui jatkuvasti. Luulen Daniin viennin takia.
shopt -s nullglob
ennen for-silmukan suorittamista.FILES=
ls * .zip; for fname in "${FILES}"...
, mutta se toimii odotetustifor fname in *.zip ; do....
for file in *.zip
, ei`ls ...`
. @cuonglm ' ehdotus on niin, että*.zip
laajenee mihinkään, kun kuvio ei ole ' ei vastaa mitään tiedostoa.ls
ilman argumentteja listaa nykyisen hakemiston.ls
-lähdön jäsentäminen on yleensä vältetään: Miksi ei jäsennäls
? ; katso myös sivun yläosassa oleva linkki BashGuide ' s ParsingLs-artikkeliin.