' ls -1 ': Sådan vises filnavne uden udvidelse

ls -1 lister mine elementer sådan:

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

Jeg vil have det opført uden .png sådan:

foo bar foobar ... 

(dir indeholder kun .png filer)

Kan nogen fortælle mig, hvordan jeg bruger grep i dette tilfælde?

Formål: Jeg har en tekstfil, hvor alle navnene er anført uden udvidelse. Jeg vil lave et script, der sammenligner tekstfilen med mappen for at se, hvilken fil der mangler.

Kommentarer

  • Du vil være forsigtig med en anmodning som denne. Linux har ikke filnavneudvidelser. Linux har filnavne, der muligvis indeholder en . i dem. Selvom konventionen siger at navngive dine filer med .png i slutningen, er der ingen grund til, at jeg ‘ ikke kan have en png-fil med navnet foo.zip eller my.picture.20160518 eller bare mypic.
  • @hymie I ved, men mine elementer i den mappe er alle navngivet med .png i slutningen.
  • Hvad ‘ er en ” udvidelse “? At ‘ ikke er en del af Unix-filnavnet; det ‘ s overførsel fra VMS / NT / Windows uanset hvad. Og I unge kommer også fra min græsplæne. 🙂
  • Lad ‘ ikke overdrive dette. OS behandler udvidelser som simpelthen en del af filnavnet, men masser af unix-programmer er opmærksomme på dem, fra compileren til GUI. Konceptet er bestemt ikke fremmed for unix.
  • Det anbefales normalt at undgå at analysere output af ls og til at røre output fra ls og find, hovedsagelig fordi muligheden for at pådrage sig i newline,` tab char i filnavnet. Hvis filnavnet er The new art of working on .png\NEWLINE files and other formats, vil mange af den foreslåede løsning skabe problemer.

Svar

Du har kun brug for shell til dette job.

POSIXly:

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

Med zsh:

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

Kommentarer

  • Der ‘ er ikke behov for printf; echo ${f%.png} er tilstrækkelig.
  • @Conrad: brug af ekko vandt ‘ t fungerer korrekt i nogle tilfælde, hvis filnavnet start med bindestreg eller indehold undslipte sekvenser.
  • @DavidConrad: Se også unix.stackexchange.com/a/65819/38906
  • @ DavidConrad Derudover mener jeg, at printf er indbygget, ligesom ekko, nogen retter mig, hvis jeg ‘ tager fejl

Svar

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

sed -kommandoen fjerner (dvs. den erstatter med den tomme streng) enhver streng .png fundet i slutningen et filnavn.

. undslippes som \., så det fortolkes af sed som et bogstaveligt . tegn snarere end regexp . (hvilket betyder at matche enhver ch aracter). $ er slutningen af linjeankeret, så det matcher ikke .png midt i et filnavn.

Kommentarer

  • Jeg tror, at OP vil have enhver udvidelse fjernet, men sandsynligvis kun ” sidste “. Så måske rediger dit ellers gode svar med: sed 's/\.[^.]*$//'
  • ja, den regexp ville arbejde i så fald … men hvis OP ønsker det, skal de sige det i stedet for specifikt at sige, at de ” vil have det opført uden .png ”
  • -1 er ikke nødvendigt, da det er standard her.
  • @jlliagre Jeg er enig i cas, at -1 skal specificeres. Det ‘ er kun standard, når rør er tændt, hvilket er en skjult overraskelse for nogle. Så at gøre det eksplicit hjælper Jeg gør det også i mine scripts, så jeg ved, hvilken slags o udgang I ‘ jeg forventer.
  • Advarsel I tilfælde af et filnavn med nøglen (.png) før en ny linjetegn sletter du selv den .png og ikke kun den sidste. Det er bedre at undgå at pibe og analysere output fra ls, det forbeholder sig ofte godt skjulte overraskelser … (nogle ord og referencer mere i svaret).

Svar

Hvis du bare vil bruge bash:

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

Du skal nå til grep når du prøver at finde match, ikke for at fjerne / erstatte det sed mere passende:

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

Når du først har besluttet at du skal oprette nogle underkataloger for at bringe orden i dine PNG-filer, kan du nemt ændre det til:

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

Kommentarer

  • ls -1 | sed ‘ s / .png // ‘ fungerer godt. Tak!
  • find piped til sed løsningen kan give nogle problemer, hvis du finder en fil med nøglen (.png) som en del af navnet og lige før et nyt linjetegn. Det er bedre at undgå at pibe og analysere output fra find eller ls, det forbeholder sig ofte godt skjulte overraskelser … (nogle ord og referencer mere i svaret).
  • Erstat sandsynligvis find med noget som echo i det sidste eksempel. Ikke klart, hvilket formål find tjener der, og resultaterne afhænger af katalogstrukturen (dvs. hvis du har en mappe files.png)
  • @BroSlow Opdateret til noget mere fornuftigt.

Svar

Et andet meget lignende svar (jeg er overrasket over dette en bestemt variant har ikke vist sig endnu er:

ls | sed -n "s/\.png$//p" 
  • Du behøver ikke -1 mulighed for at ls, da ls antager, at hvis standardoutputtet ikke er en terminal (det er et rør, i dette tilfælde).
  • indstillingen -n til sed betyder ikke udskrive linjen som standard
  • indstillingen /p i slutningen af udskiftningen betyder … og udskriv denne linje, hvis der blev foretaget en udskiftning.

Nettet effekten af det er kun at udskrive de linjer, der ender på .png, med fjernet. Det vil sige, dette henvender sig også til den lette generalisering af OPs spørgsmål, hvor kataloget ikke kun indeholder .png filer.

sed -n -teknik er ofte nyttig i tilfælde, hvor du ellers måske bruger grep + sed.

Kommentarer

  • Jeg kan godt lide, hvordan plejen du plejede at skrive dit svar. Denne løsning præsenterer problemer med filnavne inklusive nye linjer , den udskriver ikke den første del af navnet. Endnu mere, hvis det er en smukkere med nøglen (.png) før den nye linjetegn: i så fald vil du udskrive den del uden png og ikke kun slette den sidste del. Det anbefales ofte at undgå at analysere (og pibe) output fra ls fordi problemerne kan skjules lige hvor du ikke tænker på …
  • @Hastur Du ‘ er korrekt i princippet og den berømte side om don ‘ t parse ls viser yderligere problemer (og løsninger) ved aflevering af patologiske filnavne. Men den bedste måde at håndtere det på er at undgå at have patologiske filnavne (doh!); og hvis du kan ‘ t, eller hvis du skal være robust over for dem, skal du enten bruge find eller – muligvis bedre – brug et mere kraftfuldt sprog end sh til at styre dem (det faktum at sh kan gøre alt betyder ikke ‘ t, at det ‘ er det bedste valg i hvert tilfælde). Skallen er designet til brugervenlighed først.
  • Jeg er principielt enig i anvendeligheden, men denne variant mislykkes, når du har et filnavn med hver ny linje indeni. Dette kan let forekomme ubemærket, for eksempel når du kopierer og indsætter en linje fra en pdf i en GUI, så du tænker kun at undgå patologiske filnavne .
  • Desuden IMHO Det er ‘ let at begynde at parse ls, men det er en række fremtidige problemer. Ofte laver vi scripts som vi vil bruge senere, når vi allerede vil glemme deres grænse … (det ‘ s menneske, det ‘ er normalt). Jeg foreslog et find eksempel (med -exec og uden rør) selvom jeg anser det for bedre (fordi ren skal) besvare cuonglm ‘ s en , solid og posix-kompatibel.
  • Dette er stort set det, jeg ‘ d gjorde, hvis jeg af en eller anden grund ville fjerne strip .png suffiks fra en liste over filnavne.Jeg ville ikke ‘ ikke sætte det i et script; i stedet skrev jeg ‘ bare kommandoen ved shellprompten. Dette ville være en påmindelse om, at jeg ‘ m antager ” sane ” filnavne. Der er masser af ting, jeg ‘ gør i en engangs manuel kommando, når jeg er fri til at antage, hvad ‘ s i den aktuelle mappe, som jeg sandsynligvis ikke ville ‘ ikke gøre i et script, der muligvis genbruges i en anden sammenhæng.

Svar

Jeg ville gå til basename (forudsat GNU-implementering):

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

Kommentarer

  • Bemærk, at hvis du vil bruge det i et rør, kan det være nyttigt at bruge GNU-basenavn ‘ s -z (eller --zero) mulighed for at producere NUL-adskilt (i stedet for newline-adskilt ) output.

Svar

Du kan kun bruge BASH-kommandoer til at gøre det (uden eksterne værktøjer).

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

Dette er nyttigt, når du “er uden / usr / bin og fungerer godt til filnavne l ike this.is.image.png og for alle udvidelser.

Svar

var det ikke nok?

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

eller generelt fjerner dette

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

alle udvidelser

Kommentarer

  • Det var, men de andre løsninger fungerer også.
  • Alt Unix / Unix-lignende system har (eller burde have) sed, da det er et obligatorisk hjælpeprogram af standarden.
  • Faktisk, men ls gør det alligevel uden denne mulighed, når dens output ikke er en terminal, hvilket er tilfældet her.
  • Advarsel ls -1 | sed 's/\.[a-z]*//g' mislykkes, hvis der er et filnavn, da Image.png.jpg.png klipper hele tiden nøglen (.png). Under Unix er underlige filnavne tilladt som The new art of working on .png?files and other formats.png hvor ? er en newline-karakter. Desværre er al den løsning, der simpelthen vil pibe / parsere ls output, i proble ms administrerer sådanne sager …
  • Hvorfor g kvalifikationen? Du vil kun fjerne \.png i slutningen af linjen, ikke hver gang den vises.

Svar

Det er ikke sikkert at parse ls eller at røre find [ 1 , 2 ]

Det er ikke sikkert at parse (og til rør) output fra ls eller find, hovedsageligt fordi det er muligt at finde i filnavne ikke-sædvanlige tegn som newline , fanen … Her fungerer en ren skalcyklus [ cuonglm ] .
Selv find kommandoen ikke piped med indstillingen -exec fungerer:

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

Opdateringer / noter : Du kan bruge find . til at søge selv efter de skjulte filer eller find ./*.png for kun at få de ikke skjulte. Med find *.png -exec ... kan du have problemer, hvis det var en fil med navnet .png, fordi find får det som en mulighed. Du kan tilføje -maxdepth 0 for at undgå at komme ned i mapper med navnet Dir_01.png eller find ./*.png -prune -exec ... maxdepth er ikke tilladt (tak Stéphane). Hvis du vil undgå at liste disse mapper, skal du tilføje indstillingen -type f (som også udelukker andre typer ikke-almindelige filer). Se det man for et mere komplet panorama om alle tilgængelige muligheder, og husk at kontrollere, hvornår de er POSIX-kompatible, for en bedre bærbarhed.

Nogle ord mere

Det kan f.eks. ske, at kopiering af titlen fra et dokument og indsættelse i filnavnet, en eller flere nye linjer slutter i selve filnavnet.Vi kan endda være så uheldige, at en titel kan indeholde selv den nøgle, vi skal bruge lige før en ny linje:

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

Hvis du vil teste, kan du Opret filnavne som dette med kommandoerne

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" 

Den enkle /bin/ls *png vil output ? i stedet for de ikke-printbare tegn

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

I alle de tilfælde, hvor du vil rør output af ls eller find den følgende kommando har intet tip til at forstå hvis den aktuelle linje kommer fra et nyt filnavn eller hvis det følger et newline tegn i det præcedens filnavn . Et grimt navn faktisk, men stadig et lovligt navn.

En skalcyklus med en skal Parameter-udvidelse, ${parameter%word}, i begge varianten med printf eller echo fungerer [ cuonglm ], [ Anthon1 ] .

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

Fra mandsiden af shell-parameterudvidelsen [ 3 ]

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

… resultatet af udvidelsen er værdien af parameteren med det korteste matchende mønster (tilfældet %) eller længste matchende mønster (%% sagen) slettet.

Kommentarer

  • Også resultaterne af din find kommando er en smule variabel (for eksempel hvis der er en mappe kaldet files.png)
  • Kære @BroSlow, da jeg skrev svaret ovenfor I forsøgte 13 (alle) de andre varianter, der var til stede i det øjeblik, ved kommandolinje i et script, der blev lanceret som argument for en shellopkald. Venligst gør det samme, og fortæl mig, om de opfører sig som du forventer. Jeg lavede mine tests med bash 4.3.11, bindestreg 0.5.7-4, zsh (når det var nødvendigt) 5.0.2. Du er velkommen til at læse dette indlæg , der tilføjer noget mere. Jeg er enig i noten om piping output fra find, for dette

, og jeg skrev i titlen.:-).

  • Genlæs wikien igen. Jeg tror stadig, at du har brug for at pibe i dit eksempel, da det ‘ er, hvad ‘ diskuteres her. Og for de fleste moderne versioner af ls er der intet overhovedet noget problem, når output sendes eller omdirigeres, men som nævnt i wiki fungerer det muligvis ikke for alle. De fleste indsætter kun ? i stedet for specialtegn, når output sendes til terminal. dvs. gør echo *.png | od -c og ls *.png | od -c. Nyhedsproblemet er ikke et problem med ls, det ‘ er et problem med enhver kommando, der ikke ‘ t null afsluttes på tværs af begge sider af røret.
  • printf "${f%.png}\n" er forkert. Det første argument er formatet, du skal ikke ‘ ikke bruge variable data derinde. Kan endda ses som en DoS-sårbarhed (prøv f.eks. Med en %1000000000s.png -fil).
  • Du ‘ d har brug for find ./*.png -prune -exec... eller du ‘ d har problemer med filnavne, der starter med - (og filer af typekatalog, bemærk at -maxdepth ikke er bærbar)
  • Svar

    Brug rev:

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

    rev vender alle strenge (linjer); du klipper alt efter den første “.” og rev vender resten tilbage.

    Hvis du vil grep “alma”:

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

    Kommentarer

    • -1 er ikke nødvendig, da det er standard her.
    • Dette mislykkes dårligt på en fil med navnet My.2016.Summer.Vacation.png
    • @DavidConrad min dårlige: / Jeg har rettet til cut -f 2-
    • Nu fungerer det med den fil, men endnu ikke med en fil med .png og en ny linje lige efter … Det anbefales at undgå at parse ls fordi det elsker at skjule overraskelserne godt … 🙂

    Svar

    Hvis jeg vidste, at biblioteket kun havde filer med .png som udvidelse, ville jeg lige have kørt: ls | awk -F. "{print $1}"

    Dette returnerer det første “felt” for alt, hvor der er et filnavn. udvidelse.

    Eksempel:

    [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 

    Kommentarer

    • Desværre vil det mislykkes på alle filnavne med mere end en ., som Image.1.png og endda på dem med ikke pæn navne med specialtegn indeni. som den nye linje eller den, du vil bruge som (input) pladeseparator i awk, RS. Det anbefales at undgå at analysere ls output, fordi det elsker at skjule et problem, der opstår, når du ikke forventer. Du kan læse mere i referencen 1 eller 2 . BTW dejlig ideen om at bruge awk … Jeg sætter nogle eksempler i et svar.
    • Sandt nok, i betragtning af den prøve, Colin leverede, ville det fungere fint. For at få det til at fungere i den sag, du foreslog, skal jeg ‘ sandsynligvis ændre det til: [rsingh @ rule51 TESTDIR] $ ls | sed -e ‘ s / .png $ // ‘ 10 1 2 3 4 5 6 7 8 9 harry.the.bunny hvad .a.png.filename Forsøger ikke at være vanskelig, men givet Colin ‘ s behov, er jeg ‘ ikke sikker på, hvad problemet ville være analyser ls.
    • undskyld … Jeg indså lige, at jeg ikke ‘ ikke viste biblioteket med filerne før sed ændrede output af ‘ 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 hvad .a.png.filename
    • note1 du skal undslippe . i \. inde i sed -e 's/\.png$//', men så bliver det et svar, der netop er skrevet. 🙁 note2 du kan prøve at bruge awk med noget som ls | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}' … men du får altid det problem, som awk ikke kan vide, om linjen ankommer, følger eller ikke en ny linje inden for filnavnet. Jeg prøvede at sige bedre i mit svar.
    • Tak Hastur, jeg savnede det :). Jeg har også fjernet brugen af awk til fordel for sed i dette tilfælde.

    Svar

    i henhold til din kommentar “Jeg har en tekstfil, hvor alle navne er anført uden udvidelsen. Jeg vil lave et PHP-script, der sammenligner tekstfilen med mappen for at se, hvilken fil der mangler”:

    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 

    og omvendt:

    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) 

    Svar

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

    Er den mest nøjagtige metode som fremhævet af @roaima. Uden de undslapte \.png filer, der hedder a_png.png, blev de vist som: a_.

    Kommentarer

    • ved hjælp af ls -l, som du gør, giver filoplysningerne, det er ikke det, OPen bad om om.

    Svar

    En simpel skalelinje (ksh, bash eller zsh; ikke bindestreg):

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

    En simpel funktion (fra Ingen udvidelse):

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

    Eller en funktion, der fjerner enhver udvidelse givet (png som standard):

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

    Brug som:

    ne jpg 

    Hvis output er en stjerne *, findes der ingen fil med denne udvidelse.

    Svar

    Du kan prøve følgende feed awk output af ls din superator er “.” og da alle dine filer vil have name.png, udskriver du den første kolonne:
    ls | awk -F"." "{print $1}"

    Svar

    Hvis du har adgang til sed, er dette bedre, da det vil fjerne den sidste filtypen, uanset hvad det er (png, jpg, tiff osv …)

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

    Kommentarer

    • Bryder til filnavne som this.is.a.dotty.txt. Prøv s/\.[^.]*$// i stedet.

    Skriv et svar

    Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *