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
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 tilsed
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 frafind
ellerls
, det forbeholder sig ofte godt skjulte overraskelser … (nogle ord og referencer mere i svaret). - Erstat sandsynligvis
find
med noget somecho
i det sidste eksempel. Ikke klart, hvilket formålfind
tjener der, og resultaterne afhænger af katalogstrukturen (dvs. hvis du har en mappefiles.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 atls
, dals
antager, at hvis standardoutputtet ikke er en terminal (det er et rør, i dette tilfælde). - indstillingen
-n
tilsed
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 frals
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 endsh
til at styre dem (det faktum atsh
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 etfind
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, daImage.png.jpg.png
klipper hele tiden nøglen (.png
). Under Unix er underlige filnavne tilladt somThe 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 / parserels
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 kaldetfiles.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 frafind
, for dette
, og jeg skrev i titlen.:-)
.
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). 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 parsels
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
.
, somImage.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 iawk
,RS
. Det anbefales at undgå at analyserels
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 ised -e 's/\.png$//'
, men så bliver det et svar, der netop er skrevet. 🙁 note2 du kan prøve at brugeawk
med noget somls | 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øvs/\.[^.]*$//
i stedet.
.
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 navnetfoo.zip
ellermy.picture.20160518
eller baremypic
.ls
og til at røre output frals
ogfind
, hovedsagelig fordi muligheden for at pådrage sig inewline
,` tab char i filnavnet. Hvis filnavnet erThe new art of working on .png\NEWLINE files and other formats
, vil mange af den foreslåede løsning skabe problemer.