' ls -1 ': kuinka tunnistaa tiedostot ilman laajennusta

ls -1 listaa elementtini näin:

foo.png bar.png foobar.png ... 

Haluan sen listattavan ilman .png näin:

foo bar foobar ... 

(dir sisältää vain .png -tiedostoja)

Voiko joku kertoa minulle, miten grep käytetään tässä tapauksessa?

Tarkoitus: Minulla on tekstitiedosto, jossa kaikki nimet on lueteltu ilman laajennus. Haluan tehdä komentosarjan, joka vertaa tekstitiedostoa kansioon nähdäksesi, mikä tiedosto puuttuu.

Kommentit

  • Haluat olla varovainen tällainen pyyntö. Linuxilla ei ole tiedostonimen laajennuksia. Linuxissa on tiedostonimiä, joihin voi sisältyä .. Vaikka yleissopimus kehottaa nimeämään tiedostosi .png lopussa, en ole mitään syytä, miksi ’ ei voi olla png-tiedostoa nimeltä foo.zip tai my.picture.20160518 tai vain mypic.
  • @hymie I tiedän, mutta kaikki tämän kansion elementtini on nimetty .png: n loppuun.
  • Mikä ’ s on ” laajennus ”? ’ ei ole osa Unix-tiedostojen nimeämistä; se ’ siirtää tietoja VMS / NT / Windowsista riippumatta. Ja te nuoret, pääset myös nurmikolleni. 🙂
  • Älköön ’ yliarvioimaan tämän. Käyttöjärjestelmä käsittelee laajennuksia yksinkertaisesti osana tiedostonimeä, mutta monet unix-ohjelmat kiinnittävät niihin huomiota kääntäjästä graafiseen käyttöliittymään. Käsite ei todellakaan ole vieras unixille.
  • Tavallisesti ehdotetaan välttävän jäsennyksen ls ja liittää ls – ja find -lähtö lähinnä siksi, että mahdollisuus esiintyä newline,` sarkainmerkki tiedostonimessä. Jos tiedostonimi on The new art of working on .png\NEWLINE files and other formats, monet ehdotetuista ratkaisuista aiheuttavat ongelmia.

Vastaa

Tarvitset vain kuoren tähän työhön.

POSIXly:

for f in *.png; do printf "%s\n" "${f%.png}" done 

Kanssa zsh:

print -rl -- *.png(:r) 

kommentit

  • Siellä ’ ei tarvita printf; echo ${f%.png} riittää.
  • @Conrad: kaiun käyttäminen ei toimi ’ ei toimi joissakin tapauksissa oikein, jos tiedoston nimi aloita viivalla tai sisältää pakotettuja sekvenssejä.
  • @DavidConrad: Katso myös unix.stackexchange.com/a/65819/38906
  • @DavidConrad Lisäksi uskon, että printf on sisäänrakennettu, aivan kuten kaiku, joku korjaa minut, jos olen ’ väärässä

Vastaus

ls -1 | sed -e "s/\.png$//" 

sed -komento poistaa (eli se korvaa tyhjän merkkijonon) mikä tahansa merkkijono .png, joka löytyy kohteen lopusta tiedostonimi.

. vältetään nimellä \., joten kirjaimellisena . -merkkinä regexp . -merkin sijaan (mikä tarkoittaa, että vastaa mitä tahansa ch: tä luonne). $ on rivin lopussa oleva ankkuri, joten se ei sovi .png tiedostonimen keskelle.

Kommentit

  • Luulen, että OP haluaa minkä tahansa laajennuksen poistamisen, mutta luultavasti vain ” viimeinen ”. Joten ehkä muokkaa muuten hyvää vastaustasi: sed 's/\.[^.]*$//'
  • kyllä, regexp olisi toimi siinä tapauksessa … mutta jos OP haluaa niin, heidän tulisi sanoa niin sen sijaan, että sanottaisiin nimenomaisesti, että he ” haluavat sen olevan luettelossa ilman .png ”
  • -1 ei ole välttämätön, koska se on tässä oletusarvo.
  • @jlliagre Olen samaa mieltä cas kanssa, että -1 tulisi määritellä. Se ’ on vain oletusarvo, kun putki kytketään päälle, mikä on piilotettu yllätys joillekin. Joten sen selkeyttäminen auttaa Teen tämän myös käsikirjoituksissani, jotta tiedän millainen o utput I ’ odotan.
  • Varoitus Jos kyseessä on avaimen sisältävä tiedostonimi (.png) ennen uuden rivin merkkiä pyyhit jopa .png eikä vain viimeisen. Parempi on välttää ls: n tuotoksen putkiminen ja jäsentäminen, se varaa usein hyvin piilotettuja yllätyksiä … (vastauksessa on joitain sanoja ja viitteitä).

Vastaa

Jos haluat käyttää vain bash-tiedostoa:

for i in *; do echo "${i%.png}"; done 

Sinun tulisi tavoittaa grep, kun yrität löytää osumia, et poista / korvaa sitä, että sed sopivampi:

find . -maxdepth 1 -name "*.png" | sed "s/\.png$//" 

Kun olet päättänyt, että sinun on luotava joitain alihakemistoja järjestyksen luomiseksi PNG-tiedostoihisi, voit vaihtaa sen helposti muotoon:

find . -name "*.png" | sed "s/\.png$//" 

Kommentit

  • ls -1 | sed ’ s / .png // ’ toimii hyvin. Kiitos!
  • find johdettu sed -ratkaisu voi aiheuttaa joitain ongelmia, jos löydät tiedoston, jonka avain (.png) on osa nimeä ja juuri ennen uuden rivin merkkiä. find – tai ls -lähtöä on parempi välttää piilottaa ja jäsentää, se varaa usein hyvin piilotettuja yllätyksiä … (joitain sanoja ja viittauksia lisää vastaukseen).
  • Korvaa todennäköisesti find viimeisellä esimerkillä jotain echo. Ei ole selvää, mikä tarkoitus find palvelee siellä ja tulokset riippuvat hakemistorakenteesta (ts. Jos sinulla on hakemisto files.png)
  • @BroSlow Päivitetty järkevämmäksi.

Vastaa

Toinen hyvin samanlainen vastaus (olen yllättänyt tämän tietty variantti ei ole vielä ilmestynyt) on:

ls | sed -n "s/\.png$//p" 
  • Et tarvitse -1 vaihtoehto ls, koska ls olettaa, että jos vakiolähtö ei ole ”ta” -liitin (tässä tapauksessa se on putki).
  • -n -vaihtoehto sed tarkoittaa ”älä tulosta viivaa oletuksena”
  • Korvauksen lopussa oleva vaihtoehto /p tarkoittaa … ja tulosta tämä rivi, jos korvaus tehtiin.

Verkko seurauksena on tulostaa vain ne rivit, jotka päättyvät .png -merkkiin poistettu. Toisin sanoen tämä palvelee myös OP: n kysymyksen hieman yleistämistä, jossa hakemisto ”ei sisällä vain .png -tiedostoja.

sed -n -tekniikka on usein hyödyllinen tapauksissa, joissa muuten saatat käyttää grep + sed-toimintoa.

Kommentit

  • Pidän hoidon tavasta kirjoitit vastauksesi. Tämä ratkaisu aiheuttaa ongelmia tiedostonimissä, mukaan lukien uudet rivit , se ei tulosta nimen ensimmäistä osaa. Vielä enemmän, jos se on ikävämpi avaimella (.png) ennen uuden rivin merkkiä: tällöin osa tulostetaan ilman png-tiedostoa eikä tyhjennetä vain viimeistä osaa. Usein ehdotetaan, että ls koska ongelmat voidaan piilottaa juuri sinne, mistä et ajattele …
  • @Hastur Sinä ’ korjata , periaatteessa, ja kuuluisa sivu aiheesta don ’ t parse ls listaa muita ongelmia (ja ratkaisuja) patologisten tiedostonimien luovutuksessa. Mutta paras tapa käsitellä sitä on välttää patologisten tiedostonimien käyttöä (doh!); ja jos pystyt ’ t tai jos täytyy olla vankka heitä vastaan, käytä joko find tai – mahdollisesti parempi – käytä tehokkaampaa kieltä kuin sh niiden hallitsemiseksi (se, että sh voi tehdä kaikki ei tarkoita ’ t, että se ’ on kussakin tapauksessa paras valinta). Kuori on suunniteltu ensin käytettäväksi.
  • Olen periaatteessa samaa mieltä käytettävyydestä, mutta tämä muunnelma epäonnistuu, kun jokaisella uudella rivillä on tiedostonimi . Tämä voi tapahtua helposti huomaamatta, esimerkiksi kun kopioit ja liität rivin pdf: stä graafiseen käyttöliittymään, joten luulet vain välttävän patologisia tiedostonimiä .
  • Lisäksi IMHO ’ on helppo aloittaa jäsentely ls, mutta se on tulevien ongelmien edessä. Teemme usein komentosarjoja jota käytämme myöhemmin, kun unohdamme jo niiden rajan … (se ’ on ihminen, se ’ on tavallista). I ehdotin esimerkkiä find (-exec ja ilman putkea) vaikka katson paremman (koska puhdas kuori), vastaa cuonglm ’ yhteen , kiinteään ja posix-yhteensopivaan.
  • Tämä on melkein mitä minä ’ tekisin, jos jostain syystä halusin poistaa nauhan .png pääte tiedostojen nimiluettelosta.En halua ’ laittaa sitä komentosarjaan; sen sijaan ’ d vain kirjoitan komennon komentokehotteeseen. Näin tekeminen olisi muistutus siitä, että olen ’ m olettaen ” järkevän ” tiedostonimet. On paljon asioita, joita ’ teen kertakäyttöisessä manuaalisessa komennossa, kun voin tehdä vapaita oletuksia siitä, mitä ’ nykyisessä hakemistossa, en todennäköisesti ’ tekisi komentosarjassa, jota saatetaan käyttää uudelleen jossakin muussa yhteydessä.

Vastaa

Menen hakemaan basename (olettaen, että GNU on toteutettu):

basename --suffix=.png -- *.png 

Kommentit

  • Huomaa, että jos haluat käyttää sitä putkessa, voi olla hyödyllistä käyttää GNU-basenimeä ’ s -z (tai --zero) vaihtoehto tuottaa NUL-erotettu (uuden rivillä erotetun sijasta) ) output.

Vastaa

Voit käyttää siihen vain BASH-komentoja (ilman ulkoisia työkaluja).

for file in *; do echo "${file%.*}"; done 

Tämä on hyödyllistä, kun olet ilman / usr / bin -ohjelmaa ja toimii mukavasti tiedostonimillä l kuten tämä.is.image.png ja kaikille laajennuksille.

vastaus

ei ollut tarpeeksi?

ls -1 | sed "s/\.png//g" 

tai yleensä tämä

ls -1 | sed "s/\.[a-z]*//g" 

poistaa kaikki laajennukset

kommentit

  • Se oli, mutta muutkin ratkaisut toimivat.
  • Kaikissa Unix / Unix Like -järjestelmissä on (tai pitäisi olla) sed asennettu, koska se on pakollinen apuohjelma standardin mukaan.
  • Tosiaankin, mutta ls tekee sen joka tapauksessa ilman tätä vaihtoehtoa, kun sen lähtö ei ole päätelaite, kuten tässä tapauksessa on.
  • Varoitus ls -1 | sed 's/\.[a-z]*//g' epäonnistuu, jos tiedostonimi Image.png.jpg.png leikkaa koko avaimen (.png). Unix-kohdassa sallitaan outoja tiedostonimiä nimellä The new art of working on .png?files and other formats.png, jossa ? on uuden rivin merkki. Valitettavasti kaikki ongelmat, jotka yksinkertaisesti liittävät / jäsentävät ls -lähdön, aiheutuvat ongelmasta MS hallitsee tällaisia tapauksia …
  • Miksi g -merkintä? Haluat poistaa \.png vain rivin lopussa, ei aina, kun se ilmestyy.

Vastaa

Ei ole turvallista jäsentää ls tai liittää find [ 1 , 2 ]

Ei ole turvallista jäsentää (ja toipua) ls – tai find -lähtö lähinnä siksi, että se löytyy tiedostojen nimistä muut kuin tavalliset merkit uusi rivi , välilehti … Tässä puhdas kuorisykli toimii [ cuonglm ] .
Jopa find -komento ei lähetetty -vaihtoehdolla -exec toimii:

find ./*.png -exec basename {} .png \; 

Päivitykset / Muistiinpanot : Voit käyttää find . -ohjelmaa jopa piilotettujen tiedostojen etsimiseen tai find ./*.png saada vain piilotetut. Kohdassa find *.png -exec ... sinulla voi olla ongelmia siinä tapauksessa, että siinä oli tiedosto nimeltä .png, koska haku saa sen vaihtoehtona. Voit lisätä -maxdepth 0 välttääksesi laskeutumista hakemistoihin nimeltään Dir_01.png tai find ./*.png -prune -exec ... kun maxdepth ei ole sallittu (kiitos Stéphane). Jos haluat välttää näiden hakemistojen luetteloimista, sinun on lisättävä vaihtoehto -type f (joka sulkisi pois myös muita epätyypillisiä tiedostoja). Tarkastele man -sivustoa saadaksesi täydellisemmän panoraaman kaikista käytettävissä olevista vaihtoehdoista. Muista tarkistaa, että ne ovat POSIX-yhteensopivia, jotta siirrettävyys paranee.

Joitakin sanoja enemmän

Voi esimerkiksi tapahtua, että kopioimalla otsikko dokumentista ja liittämällä se tiedostonimeen, yksi tai useampi uusi rivi päättyy itse tiedostonimeen.Voimme olla jopa niin onnekkaita, että otsikko voi sisältää jopa avaimen, jota meidän on käytettävä juuri ennen uutta riviä:

The new art of working on .png files and other formats. 

Jos haluat testata, voit luo tällaisia tiedostojen nimiä komennoilla

touch "A file with two lines"$"\n""and This is the second.png" touch "The new art of working on .png"$"\n""files and other formats.png" 

Yksinkertainen /bin/ls *png tuottaa ? tulostamattomien merkkien sijaan

A file with two lines?and This is the second.png The new art of working on .png?files and other formats.png 

Kaikissa tapauksissa, joissa putki -viestin ls tai find lähtöä seuraavalla komennolla ei ole vihjeitä ymmärtää jos nykyinen rivi tulee uudesta tiedoston nimestä tai jos se seuraa newline -merkkiä ennakkotapauksessa tiedoston nimi . ikävä nimi todellakin, mutta silti laillinen.

Kuorisykli, jossa on komentotulkki Parameter-Expansion, ${parameter%word}, molemmissa variantti, jossa on printf tai echo, toimii [ cuonglm ], [ Anthon1 ] .

for f in *.png; do printf "%s\n" "${f%.png}" ; done 

Man-sivulta Shell-parametrilaajennuksen [ 3 ]

$ {parametri% word}
$ {parametri %% word}

… laajennuksen tulos on parametrin arvo, jolla on lyhyin vastaava kuvio (%-tapaus) tai pisin vastaava kuvio (tapaus %%) poistettu.

Kommentit

  • Myös find -komento on bittimuuttuja (esimerkiksi jos on hakemisto nimeltä files.png)
  • Hyvä @BroSlow, kun kirjoitin vastauksen yllä I kokeillut 13 (kaikkia) muita läsnäolevia muunnelmia sillä hetkellä komentorivillä komentosarjassa, joka käynnistettiin kuoren kutsun argumenttina. Ole hyvä ja tee sama ja kerro minulle, jos he käyttäytyvät odotetulla tavalla. Tein testini bash 4.3.11 -viivalla, viiva 0,5,7-4, zsh (tarvittaessa) 5.0.2. Voit vapaasti lukea tämän viestin , joka lisää jotain enemmän. Olen samaa mieltä siitä, että piping find -lähtö on tuotu, tähän ehdotin nimenomaisesti -exec ja kirjoitin otsikkoon. :-).
  • Lue wiki uudelleen. Mielestäni sinun on edelleen esitettävä esimerkkisi, koska ’ s mitä ’ käsitellään täällä. Ja suurimmalle osalle ls -sovelluksen moderneista versioista ei ole mitään ongelmaa, kun lähtö lähetetään tai ohjataan uudelleen, mutta kuten wikissä mainitaan, se ei välttämättä toimi kaikille. Suurin osa lisää ? -merkin erikoismerkkien tilalle vain, kun lähtö lähetetään päätelaitteelle. so. tee echo *.png | od -c ja ls *.png | od -c. Uuden rivin kysymys ei ole ongelma ls, se ’ on ongelma mille tahansa komennolle, joka ei ’ t null päättyy putken molemmin puolin.
  • printf "${f%.png}\n" on väärä. Ensimmäinen argumentti on muoto, sinun ei pitäisi ’ käyttää muuttujan tietoja siellä. Voidaan jopa nähdä DoS-haavoittuvuutena (kokeile esimerkiksi %1000000000s.png -tiedostoa).
  • Sinä ’ d tarvitset find ./*.png -prune -exec... tai sinulla ’ d on ongelmia tiedostonimien kanssa, jotka alkavat - (ja kirjoita hakemisto, huomaa, että -maxdepth ei ole kannettava)

Vastaa

Käytä rev:

ls -1 | rev | cut -f 2- -d "." | rev 

rev kääntää kaikki kielet (viivat); leikkaat kaiken ensimmäisen ”” jälkeen. ja rev palauttaa jäännöksen.

Jos haluat grep ”alma”:

ls -1 | rev | cut -f 2- -d "." | rev | grep "alma" 

Kommentit

  • -1 ei ole tarpeen, koska se on tässä oletusarvo.
  • Tämä epäonnistuu huonosti tiedostossa nimeltä My.2016.Summer.Vacation.png
  • @DavidConrad my bad: / Olen korjannut tiedostoon cut -f 2-
  • Nyt se toimii kyseisen tiedoston kanssa, mutta ei vielä sellaisen tiedoston kanssa, jossa on .png ja uusi rivi heti sen jälkeen … On suositeltavaa välttää jäsentää ls koska se rakastaa piilottaa yllätykset … 🙂

Vastaa

Jos tiesin, että hakemistossa on vain tiedostoja, joiden laajennuksena on .png, olisin juuri suorittanut: ls | awk -F. "{print $1}"

Tämä palauttaa ensimmäisen ”kentän” kohteelle mitä tahansa, missä on tiedostonimi. laajennus.

Esimerkki:

[rsingh@rule51 TESTDIR]$ ls 10.png 1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png [rsingh@rule51 TESTDIR]$ ls | awk -F. "{print $1}" 10 1 2 3 4 5 6 7 8 9 

kommentit

  • Valitettavasti se epäonnistuu kaikissa tiedostonimet , joissa on enemmän kuin yksi ., kuten Image.1.png ja jopa niissä, joissa ei ole kiva nimet , erikoismerkit sisällä. uutena rivinä tai sellaisena, jota käytät (syöttö) tietueiden erottimena kohdassa awk, RS. ls -lähdön jäsentämistä on suositeltavaa välttää, koska se rakastaa piilottaa ongelman, joka syntyy, kun et odota. Voit lukea lisää viitteestä 1 tai 2 . BTW on kiva ajatus käyttää awk: tä. Lisääin joitain esimerkkejä yhteen vastaukseen.
  • Totta, kuitenkin, Colinin toimittaman näytteen perusteella se toimisi hienosti. Jotta se toimisi ehdottamassasi tapauksessa, ’ vaihdan sen todennäköisesti muotoon: [rsingh @ rule51 TESTDIR] $ ls | sed -e ’ s / .png $ // ’ 10 1 2 3 4 5 6 7 8 9 harry.pupu .a.png.filename Ei yritä olla vaikeaa, mutta kun otetaan huomioon Colinin ’ tarve, en ’ ole varma, mitä asia aiheuttaisi jäsennä ls.
  • anteeksi … tajusin juuri, etten ’ näyttänyt hakemistoa tiedostoilla ennen kuin muokkaan ’ ls ’ [rsingh @ rule51 TESTDIR] $ ls 10.png 2.png 4.png 6.png 8.png harry.pupu. png 1.png 3.png 5.png 7.png 9.png whats.a.png.filename.png [rsingh @ rule51 TESTDIR] $ ls | sed -e ’ s / .png $ // ’ 10 1 2 3 4 5 6 7 8 9 harry.pupu .a.png.tiedostonimi
  • Huomautus1 sinun on vältettävä . -kenttää kohdassa \. sisällä sed -e 's/\.png$//', mutta niin siitä tulee vasta kirjoitettu vastaus. 🙁 huomautus2 , voit yrittää käyttää awk jotain esimerkiksi ls | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}' … mutta sinulla on aina ongelma, jota awk ei tiedä, saapuuko viiva, seuraa vai ei uutta riviä tiedostonimen sisällä. Yritin sanoa vastauksessani paremmin.
  • Kiitos Hastur, unohdin sen :). Lisäksi ojensin awk: n käytön sedin hyväksi tässä tapauksessa.

Vastaa

omasi mukaan kommentti ”Minulla on tekstitiedosto, jossa kaikki nimet on lueteltu ilman laajennusta. Haluan tehdä PHP-komentosarjan, joka vertaa tekstitiedostoa kansioon nähdäksesi mikä tiedosto puuttuu”:

for file in $(cat yourlist) ; do [ -f "${file}.png" ] || { echo "$file : listed in yourlist, but missing in the directory" } done #assumes that filenames have no space... # otherwise use instead: # while IFS= read file ; do ...(same inner loop as above)... ; done < yourlist 

ja päinvastoin:

for file in *.png ; do grep "^${file%.png}$" yourlist >/dev/null || { echo "$file: present in the directory but not listed in yourlist" } done #I assume there are no spaces/tabs/? before/after names in "yourlist". Change the script accordingly if there are some (or sanitize the list) 

vastaus

ls -l | sed "s/\.png$//"

On tarkin menetelmä, jonka @roaima korosti. Ilman pakenemia \.png -tiedostoja, joiden nimi on a_png.png, luetellaan seuraavasti: a_.

Kommentit

  • ls -l, kuten teetkin, antaa tiedoston tiedot, joita OP ei pyytänyt noin.

Vastaus

Yksinkertainen kuoririvi (ksh, bash tai zsh; ei viivaa):

set -- *.png; printf "%s\n" "${@%.png}" 

Yksinkertainen toiminto (Ei laajennusta):

ne(){ set -- *.png; printf "%s\n" "${@%.png}"; } 

Tai toiminto, joka poistaa mikä tahansa annettu laajennus (png oletuksena):

ne(){ ext=${1:-png}; set -- *."$ext"; printf "%s\n" "${@%.${ext}}"; } 

Käytä nimellä:

ne jpg 

Jos lähtö on tähti *, tällä laajennuksella ei ole tiedostoa.

Vastaa

Voit kokeilla seuraavaa syötteen awk: ta, jonka superatorisi tulos on ””. ja koska kaikilla tiedostoillasi on nimi.png, tulostat ensimmäisen sarakkeen:
ls | awk -F"." "{print $1}"

Vastaa

Jos sinulla on pääsy sediin, tämä on parempi, koska se poistaa viimeisen tiedostotunnisteen riippumatta siitä, mikä se on (png, jpg, tiff jne …)

ls | sed -e "s/\..*$//" 

Kommentit

  • Katkokset tiedostonimille kuten this.is.a.dotty.txt. Kokeile sen sijaan s/\.[^.]*$//.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *