' ls -1 ': Hogyan lehet felsorolni a fájlneveket kiterjesztés nélkül

ls -1 így sorolja fel az elemeimet:

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

A így:

foo bar foobar ... 

(a dir csak .png fájlokat tartalmaz)

Valaki meg tudja mondani, hogyan kell használni az grep -t ebben az esetben?

Cél: Van egy szöveges fájlom, ahol az összes név fel van tüntetve a kiterjesztés. Olyan szkriptet szeretnék készíteni, amely összehasonlítja a szöveges fájlt a mappával, hogy megnézze, melyik fájl hiányzik.

Megjegyzések

  • Óvatosnak kell lenni egy ilyen kérés. A Linux nem rendelkezik fájlnévkiterjesztésekkel. A Linuxnak vannak olyan fájlnevei, amelyek tartalmazhatnak vagy nem tartalmazhatnak . -et. Bár a konvenció azt mondja, hogy a fájlokat a végén nevezze el .png -nek, nincs oka annak, hogy ‘ nem lehet egy foo.zip vagy my.picture.20160518 vagy csak mypic.
  • @hymie I tudom, de az abban a mappában levő elemeim mindegyikét a végén .png-vel nevezem meg.
  • Mi ‘ s egy ” kiterjesztés “? Ez ‘ nem része a Unix fájlnevezésnek; ‘ áthelyezi a VMS / NT / Windows rendszerből. És ti fiatalok is szálljatok le a gyepről. 🙂
  • Ne hagyja, hogy a ‘ túllépje ezt. Az operációs rendszer úgy kezeli a kiterjesztéseket, hogy azok egyszerűen a fájlnév részei, de rengeteg unix program figyel rá, a fordítótól kezdve a grafikus felületig. A koncepció egészen biztosan nem idegen az unix-től.
  • Általában azt javasoljuk, hogy kerülje a ls és a ls és find kimenetét csövezni, főleg azért, mert lehetőség nyílik a newline,` tab karakter a fájlnévben. Ha a fájlnév The new art of working on .png\NEWLINE files and other formats, a javasolt megoldás nagy része problémákat okoz.

Válasz

Ehhez a munkához csak a héjra van szükség.

POSIXly:

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

A következővel: zsh:

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

Megjegyzések

  • Ott ‘ nincs szükség printf -re; A echo ${f%.png} elegendő lesz.
  • @Conrad: az echo használata bizonyos esetekben ‘ nem működik megfelelően, ha a fájlnév kötőjellel kezdje, vagy tartalmazzon elhagyott szekvenciákat.
  • @DavidConrad: Lásd még: unix.stackexchange.com/a/65819/38906
  • @DavidConrad Ezenkívül úgy gondolom, hogy a printf be van építve, csakúgy, mint az echo, valaki javítson ki, ha ‘ rossz vagyok

Válasz

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

A sed parancs eltávolítja (vagyis az üres karakterlánccal helyettesít) minden olyan sztringet .png, amely a végén található egy fájlnév.

A . \. néven kerül megkerülésre, így a sed mint szó szerinti . karakter, nem pedig a regexp . (ami azt jelenti, hogy illeszkedjen bármelyik ch-hez jelleg). A $ a sor végének horgonya, ezért nem egyezik a .png fájlnév közepén.

Hozzászólások

  • Azt hiszem, hogy az OP bármilyen kiterjesztést meg akar törölni, de valószínűleg csak a ” utolsó “. Tehát módosítsa az egyébként jó válaszát a következővel: sed 's/\.[^.]*$//'
  • igen, ez a regexp működik ebben az esetben … de ha az OP ezt akarja, akkor azt kell mondaniuk, ahelyett, hogy kifejezetten azt mondanák, hogy ” azt akarják, hogy a .png ”
  • A -1 nem szükséges, mivel itt az alapértelmezett.
  • @jlliagre Egyetértek a cas véleményével, hogy a -1 meg kell adni. ‘ csak akkor van alapértelmezés, amikor a cső be van kapcsolva, ami némelyek számára rejtett meglepetés. Tehát annak egyértelművé tétele segít Ezt a forgatókönyveimben is megteszem, így tudom, hogy milyen o utput I ‘ m várok.
  • Figyelmeztetés A (.png) egy újsoros karakter előtt még azt az .png -t is törli, és nem csak az utolsót. Jobb elkerülni az ls kimenetének csempézését és elemzését, gyakran jól rejtett meglepetéseket tartogat … (néhány szó és hivatkozás bővebben a válaszban).

Válasz

Ha csak a bash-t szeretné használni:

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

Az grep címre kell törekednie, amikor megpróbál találni egyezéseket, nem pedig a sed megfelelőbb:

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

Ha úgy dönt, hogy létre kell hoznia néhány alkönyvtárat, hogy rendet lehessen hozni a PNG-fájlokban, akkor könnyen módosíthatja:

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

Megjegyzések

  • ls -1 | A sed ‘ s / .png // ‘ remekül működik. Köszönjük!
  • A find a sed megoldás a sed megoldással problémákat okozhat, ha talál egy fájlt, amelynek kulcsa (.png) szerepel a név részeként és közvetlenül egy újsoros karakter előtt. Jobb elkerülni a find vagy a ls kimenetének csövezését és elemzését, gyakran jól rejtett meglepetéseket tartogat … (néhány szó és a válaszban többet utal).
  • Valószínűleg az find -t cserélje le valamire, például az echo kifejezésre az utolsó példában. Nem világos, hogy a find milyen célt szolgál ott, és az eredmények a könyvtárstruktúrától függenek (azaz van-e könyvtárad files.png)
  • @BroSlow Frissítve valami értelmesebbre.

Válasz

Egy másik nagyon hasonló válasz (ezen meglepődtem egy adott változat még nem jelent meg):

ls | sed -n "s/\.png$//p" 
  • Nem kell a -1 opció a ls lehetőségre, mivel a ls feltételezi, hogy ha a standard kimenet nem “ta terminál (ebben az esetben ez a cső).
  • a -n opció a sed opcióra azt jelenti, hogy “ne nyomtassa ki a sort alapértelmezés szerint”
  • a /p opció a helyettesítés végén azt jelenti: “… és nyomtassa ki ezt a sort, ha helyettesítés történt”.

A net ennek az a következménye, hogy csak azokat a sorokat nyomtatja ki, amelyek .png végződésűek, eltávolítva. Vagyis ez kielégíti az OP kérdésének enyhe általánosítását is, ahol a könyvtár nem “csak .png fájlokat tartalmaz.

A technika gyakran hasznos azokban az esetekben, amikor egyébként használhatja a grep + sed programot.

Megjegyzések

  • Tetszik az ellátás módja régebben írtad a választ. Ez a megoldás problémákat fog okozni a fájlnevekben, beleértve az új sorokat , nem fogja kinyomtatni a név első részét. Még inkább, ha csúnyább a kulccsal (.png) az újsoros char előtt: ebben az esetben az alkatrészt png nélkül nyomtatja ki, és nem csak az utolsó részt törli. Gyakran javasoljuk, hogy elkerülje a ls, mert a problémák éppen ott rejtőzhetnek, ahol nem gondolkodik …
  • @Hastur Ön ‘ helyes , elvileg, és a híres oldal erről: don ‘ t parse ls további problémákat (és megoldásokat) sorol fel a kóros fájlnevek átadásakor. De a kezelés legjobb módja az, ha elkerüljük a kóros fájlnevek t (doh!); és ha tud ‘ t, vagy ha kell robusztusnak lenni velük szemben, akkor vagy használjon find vagy – esetleg jobb – használjon erősebb nyelvet, mint a sh, mint azok kezelésére (az a tény, hogy sh képes minden nem ‘ nem jelenti azt, hogy ‘ minden esetben a legjobb választás). A héjat először a használhatóságra tervezték.
  • Elvileg egyetértek a használhatósággal kapcsolatban, de ez a változat kudarcot vall, ha minden egyes új sorban fájlnév van. Ez könnyen észrevétlenül történhet, például amikor egy sort egy pdf-ből másol és beilleszt egy GUI-ba, így csak azt gondolja, hogy kerülje a kóros fájlneveket .
  • Ezenkívül az IMHO ‘ könnyű elkezdeni értelmezni a ls elemzést, de a jövőbeni problémákkal küzd. Gyakran készítünk szkripteket amit később használunk, amikor már elfelejtjük a határértéküket … (ez ‘ s ember, ez általában ‘ s). javaslatot tettem egy find példára (-exec és cső nélkül) akkor is, ha jobbnak (mert a tiszta héjnak) tartom, válaszoljon a cuonglm ‘ s , szilárd és posix kompatibilisre.
  • Nagyjából ezt tenném ‘, ha valamilyen okból el akarnám távolítani a csíkot a .png utótag a fájlnevek listájából.Nem ‘ nem tenném szkriptbe; ehelyett ‘ d csak beírom a parancsot a shell parancssorba. Ezzel emlékeztetne arra, hogy ‘ m feltételezem ” ésszel ” fájlnevek. Rengeteg olyan dolog van, amit ‘ egyszeri kézi parancsban teszek meg, amikor nyugodtan tehetek feltételezéseket arról, hogy mi ‘ az aktuális könyvtárban valószínűleg nem ‘ tennék egy olyan szkriptben, amelyet esetleg más kontextusban is újra felhasználhatnának.

Válasz

A következőre megyek: basename (feltételezve a GNU megvalósítását):

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

megjegyzések

  • Ne feledje, hogy ha csőben akarja használni, akkor hasznos lehet a GNU basename ‘ s -z (vagy --zero) opció NUL-elválasztással (új sorral elválasztva) ) kimenet.

Válasz

Erre csak BASH parancsokat használhat (külső eszközök nélkül).

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

Ez akkor hasznos, ha a / usr / bin nélkül van, és szépen működik a l Ilyen az is.

Válasz

nem volt elég?

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

vagy általában, ez

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

eltávolítja az összes kiterjesztést

Megjegyzések

  • Ez volt, de a többi megoldás is működik.
  • Minden Unix / Unix Like rendszer telepítve van (vagy kellett volna) sed, mivel ez egy kötelező segédprogram a szabvány szerint.
  • Valóban, de a ls egyébként is megteszi ezt az opciót, ha a kimenete nem terminál, amire ez a helyzet.
  • Figyelmeztetés ls -1 | sed 's/\.[a-z]*//g' nem fog sikerülni, ha van egy fájlnév Image.png.jpg.png néven, amikor a kulcs folyamatosan vágódik (.png). A Unix alatt furcsa fájlnevek The new art of working on .png?files and other formats.png néven engedélyezettek, ahol a ? egy új vonalas karakter. Sajnos minden olyan probléma felmerül, amely a ls kimenetet egyszerűen csövezi / elemzi. ms ilyen esetek kezelése …
  • Miért a g minősítő? A \.png üzenetet csak a sor végén szeretné eltávolítani, nem minden alkalommal, amikor megjelenik.

Válasz

Nem biztonságos a ls elemzése vagy a find [ 1 , 2 ]

Nem biztonságos a ls vagy a find kimenetét elemzi (és átadja), főleg azért, mert a fájlnevekben nem szokásos karakterek, mint az új sor , a fül … Itt egy tiszta shell ciklus fog működni [ cuonglm ] .
Még a find parancs is not piped a -exec működni fog:

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

Frissítések / megjegyzések : A find . segítségével akár a rejtett fájlokat is megkeresheti, vagy find ./*.png hogy csak a nem rejtetteket kapja meg. A find *.png -exec ... használatával problémát okozhat, ha egy .png nevű fájl volt jelen, mert a find opcióként kapja meg. Hozzáadhat -maxdepth 0, hogy elkerülje a Dir_01.png vagy find ./*.png -prune -exec ... nevű könyvtárakban való leereszkedést. maxdepth nem megengedett (köszönöm Stéphane). Ha el akarja kerülni a könyvtárak felsorolását, adja hozzá a -type f opciót (amely kizárna más, nem szabályos fájlokat is). Nézze meg a man t, hogy teljesebb körképet nyújtson az összes rendelkezésre álló lehetőségről, és ne felejtse el ellenőrizni, hogy a POSIX-kompatibilisek-e a jobb hordozhatóság érdekében.

Néhány szó tovább

Előfordulhat például, hogy ha a dokumentumról lemásolja a címet és beilleszti a fájlnévbe, egy vagy több új sor a fájlnévben is befejeződik.Még olyan szerencsétlenek is lehetünk, hogy egy cím tartalmazhatja azt a kulcsot is, amelyet közvetlenül az új sor előtt kell használnunk:

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

Ha tesztelni szeretne, akkor hozzon létre ilyen fájlneveket a parancsokkal

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" 

Az egyszerű /bin/ls *png ? a nem nyomtatható karakterek helyett

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

Minden esetben, amikor a ls vagy find kimenetet csatolja, a következő parancsnak nem lesz megértése ha a jelenlegi sor új fájlnévből származik, vagy ha egy újsor karaktert követ a precedens fájlnév ben. Valóban csúnya név, de még mindig törvényes.

Egy shell-ciklus egy Parameter-Expansion héjjal, ${parameter%word}, mindkettőben a (z) printf vagy echo változata [ cuonglm ], [ Anthon1 ] .

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

A man oldalról a Shell paraméter kibővítésének [ 3 ]

$ {parameter% word}
$ {parameter %% word}

… a kiterjesztés eredménye a legrövidebb egyezési mintájú (% eset) vagy a a leghosszabb egyező minta (a %% eset) törölve.

Megjegyzések

  • Szintén a find parancs egy kicsit változó (például ha létezik egy files.png nevű könyvtár)
  • Kedves @BroSlow, amikor a választ fentebb írtam I 13 (az összes) abban a pillanatban jelen lévő változat ból próbálkozott, parancssoronként, egy parancsfájlban, amelyet egy shell meghívás argumentumaként indítottak el. Kérem, tegye ugyanezt, és mondja el, ha a várt módon viselkednek. Tesztjeimet a következővel végeztem: bash 4.3.11, dash 0.5.7-4, zsh (ha szükséges) 5.0.2. Nyugodtan olvassa el ezt a bejegyzést , amely még valamit hozzáad. Egyetértek a piping megjegyzésével a find kimeneténél, ehhez kifejezetten javasoltam -exec és a címbe írtam. :-).
  • Olvassa el újra a wikit. Még mindig úgy gondolom, hogy meg kell adnia a példáját, mivel ‘ ez az, amit ‘ tárgyalunk itt. A ls modern verzióinak többségéhez nincs semmi probléma, amikor a kimenetet átirányítják vagy átirányítják, de amint a wiki említi, nem biztos, hogy mindenki számára használható. A legtöbb csak akkor fogja beilleszteni a ? -t a speciális karakterek helyébe, ha a kimenetet a terminálra küldi. azaz tegye a következőt: echo *.png | od -c és ls *.png | od -c. Az újsoros probléma nem a ls probléma, hanem ‘ minden olyan parancs problémája, amely nem ‘ t null végződik a cső mindkét oldalán.
  • printf "${f%.png}\n" téves. Az első argumentum a formátum, nem szabad ‘ használni a változó adatokat. Akár DoS-sebezhetőség is lehet (próbálkozzon például egy %1000000000s.png fájllal).
  • Ön ‘ d find ./*.png -prune -exec... szükséges, vagy ‘ d problémái vannak a - kezdetű fájlnevekkel írja be a könyvtárat, vegye figyelembe, hogy az -maxdepth nem hordozható)

Válasz

A rev használata:

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

rev megfordítja az összes húrok (vonalak); mindent levágsz az első “” után. és a rev újra megfordítja a maradékot.

Ha grep “alma” -t szeretne:

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

Megjegyzések

  • A -1 nem szükséges, itt ez az alapértelmezett.
  • Ez csúnyán meghiúsul a My.2016.Summer.Vacation.png
  • @DavidConrad my bad: / javítottam a következőre: cut -f 2-
  • Most azzal a fájllal működik, de még nem egy .png és egy új vonallal rendelkező fájllal … Javasoljuk, hogy ne elemezze a ls mert nagyon szereti elrejteni a meglepetéseket … 🙂

Válasz

Ha tudnám, hogy a könyvtárban csak olyan fájlok vannak, amelyek kiterjesztése .png, akkor csak futtattam volna: ls | awk -F. "{print $1}"

Ez visszaadja az első “mezőt” a következőre: bármi, ahol van fájlnév.kiterjesztés.

Példa:

[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 

Megjegyzések

  • Sajnos ez nem fog sikerülni a fájlnevek egynél több . névvel, Image.1.png néven, sőt a nem szépeknél is nevek , benne speciális karakterekkel. új vonallal vagy azzal, amelyet (beviteli) rekord elválasztóként fog használni a awk, RS mezőben. Javasoljuk, hogy kerülje a ls kimenet elemzését, mert imádja elrejteni azokat a problémákat, amelyek felmerülnek, amikor nem számíthat rá. További információt a 1 vagy a 2 hivatkozásban talál. A BTW jó ötlet az awk használatára … Néhány példát egy válaszba adtam.
  • Igaz, azonban a Colin által nyújtott minta alapján ez nagyon jól fog működni. Annak érdekében, hogy az Ön által javasolt esetnek megfelelően működjön, ‘ valószínűleg módosítom a következőre: [rsingh @ rule51 TESTDIR] $ ls | sed -e ‘ s / .png $ // ‘ 10 1 2 3 4 5 6 7 8 9 harry.the.bunny izé .a.png.filename Nem próbál nehéz lenni, de tekintettel a Colin ‘ szükségleteire, nem vagyok biztos abban, id = “cb80420c6c”>

ls elemzése.

  • sajnálom … rájöttem, hogy nem mutattam ‘ a könyvtárat a fájlokkal, mielőtt módosítottam volna a ‘ ls ‘ [rsingh @ rule51 TESTDIR] $ ls 10.png 2.png 4.png 6.png 8.png harry.the.bunny. 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.the.bunny izé .a.png.filename
  • note1 meg kell menekülnie a . alól a \. belsejében a sed -e 's/\.png$//', de így az imént írt válasz lesz belőle. 🙁 note2] megpróbálhatja használni a awk -t valami hasonlóval, mint ls | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}' … de meglesz mindig az a probléma merül fel, hogy az awk nem tudja, hogy a sor érkezik-e, a fájlnév új sorát követi vagy sem. Próbáltam jobbat mondani a válaszomban.
  • Köszönöm Hastur, ezt elmulasztottam :). Emellett az awk használatát is elvetettem ebben az esetben a sed javára.
  • Válasz

    az Ön szerint comment “Van egy szöveges fájlom, ahol az összes név kiterjesztés nélkül szerepel. Szeretnék egy PHP szkriptet készíteni, amely összehasonlítja a szöveges fájlt a mappával, hogy megnézze, melyik fájl hiányzik”:

    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 

    és fordítva:

    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) 

    Válasz

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

    A @roaima által kiemelt legpontosabb módszer. A megúszott \.png fájlok nélkül a a_png.png nevű fájlok a következők lehetnek: a_.

    Megjegyzések

    • A ls -l használatával, ahogy te teszed, megadod a fájl adatait, az OP nem ezt kérte kb.

    Válasz

    Egyszerű shell sor (ksh, bash vagy zsh; nem kötőjel):

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

    Egyszerű függvény (nem kiterjesztésből):

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

    Vagy egy olyan funkció, amely eltávolítja bármely megadott kiterjesztés (alapértelmezés szerint png):

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

    Használja:

    ne jpg 

    Ha a kimenet csillag *, akkor nincs ilyen kiterjesztésű fájl.

    Válasz

    Kipróbálhatja a következő feed awk-t. A szuperátorod kimenete a “”. és mivel minden fájljának neve lesz.png, kinyomtatja az első oszlopot:
    ls | awk -F"." "{print $1}"

    Válasz

    Ha van hozzáférése a sed-hez, akkor ez jobb, mivel az utolsó fájlkiterjesztést eltávolítja, függetlenül attól, hogy mi ez (png, jpg, tiff stb …)

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

    Megjegyzések

    • Szünetek olyan fájlnevekhez, mint this.is.a.dotty.txt. Próbáld meg inkább a s/\.[^.]*$// -t.

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük