ls -1
lister elementene mine slik:
foo.png bar.png foobar.png ...
Jeg vil at den skal være oppført uten .png
slik:
foo bar foobar ...
(dir inneholder bare .png
filer)
Kan noen fortelle meg hvordan jeg bruker grep
i dette tilfellet?
Formål: Jeg har en tekstfil der alle navnene er oppført uten Utvidelse. Jeg vil lage et skript som sammenligner tekstfilen med mappen for å se hvilken fil som mangler.
Kommentarer
Svar
Du trenger bare skallet for denne jobben.
POSIXly:
for f in *.png; do printf "%s\n" "${f%.png}" done
Med zsh
:
print -rl -- *.png(:r)
Kommentarer
- Der ‘ trenger ikke
printf
;echo ${f%.png}
vil være tilstrekkelig. - @Conrad: bruk av ekko vant ‘ t fungerer i noen tilfeller riktig, hvis filnavnet start med bindestrek eller innehold rømte sekvenser.
- @DavidConrad: Se også unix.stackexchange.com/a/65819/38906
- @ DavidConrad I tillegg tror jeg printf er innebygd, akkurat som ekko, noen retter meg hvis jeg ‘ tar feil
Svar
ls -1 | sed -e "s/\.png$//"
sed
-kommandoen fjerner (det vil si den erstatter med den tomme strengen) hvilken som helst streng .png
funnet i slutten et filnavn.
.
unnslippes som \.
slik at det tolkes av sed
som et bokstavelig .
-tegn i stedet for regexp .
(som betyr at alle ch aracter). $
er slutten på linjeankeret, så det samsvarer ikke med .png
midt i et filnavn.
Kommentarer
- Jeg tror OP vil ha enhver utvidelse fjernet, men sannsynligvis bare » siste «. Så kanskje endre det ellers gode svaret ditt med:
sed 's/\.[^.]*$//'
- ja, den regexp ville fungerer i så fall … men hvis OP vil ha det, bør de si det i stedet for å spesifikt si at de » vil at det skal være oppført uten .png »
-
-1
er ikke nødvendig, som standard her. - @jlliagre Jeg er enig med cas at
-1
bør spesifiseres. Det ‘ er bare standard når rør er slått på, noe som er en skjult overraskelse for noen. Så å gjøre det eksplisitt hjelper Jeg gjør dette også i skriptene mine, slik at jeg vet hva slags o utgang jeg ‘ jeg forventer. - Advarsel I tilfelle et filnavn med nøkkelen (
.png
) før en nylinjetegn vil du slette til og med den.png
og ikke bare den siste. Det er bedre å unngå å pipe og analysere utdataene fra ls, det reserverer ofte godt skjulte overraskelser … (noen ord og referanser mer i svaret).
Svar
Hvis du bare vil bruke bash:
for i in *; do echo "${i%.png}"; done
Du bør nå grep
når du prøver å finne treff, ikke for å fjerne / erstatte det som sed
mer passende:
find . -maxdepth 1 -name "*.png" | sed "s/\.png$//"
Når du bestemmer deg for at du må opprette noen underkataloger for å få orden i PNG-filene dine, kan du enkelt endre det til:
find . -name "*.png" | sed "s/\.png$//"
Kommentarer
- ls -1 | sed ‘ s / .png // ‘ fungerer bra. Takk!
-
find
piped tilsed
løsningen kan by på noen problemer hvis du finner en fil med nøkkelen (.png
) som en del av navnet og like før et nytt linjetegn. Det er bedre å unngå å pipe og analysere utgangen avfind
ellerls
, det reserverer ofte godt skjulte overraskelser … (noen ord og referanser mer i svaret). - Erstatt sannsynligvis
find
med noe sånt somecho
i det siste eksemplet. Ikke klart hvilket formålfind
tjener der, og resultatene avhenger av katalogstruktur (dvs. hvis du har en katalogfiles.png
) - @BroSlow Oppdatert til noe mer fornuftig.
Svar
Et annet veldig likt svar (jeg overrasket dette bestemt variant har ikke vist seg ennå) er:
ls | sed -n "s/\.png$//p"
- Du trenger ikke
-1
alternativ tills
, sidenls
forutsetter at hvis standardutgangen ikke er en terminal (det er et rør, i dette tilfellet). -
-n
alternativet tilsed
betyr «ikke skriv ut linjen som standard» - alternativet
/p
på slutten av erstatningen betyr «… og skriv ut denne linjen hvis det ble foretatt en erstatning».
Nettet effekten av det er å skrive ut bare linjene som ender på .png
, med fjernet. Dette henvender seg også til en liten generalisering av OPs spørsmål, der katalogen ikke bare inneholder .png
filer.
sed -n
teknikk er ofte nyttig i tilfeller der du ellers kan bruke grep + sed.
Kommentarer
- Jeg liker hvordan pleien du pleide å skrive svaret. Denne løsningen vil gi problemer med filnavn, inkludert nye linjer , den vil ikke skrive ut den første delen av navnet. Enda mer hvis det er en styggere med nøkkelen (
.png
) før den nye linjen: i så fall vil du skrive ut den delen uten png, og ikke slette bare den siste delen. Det anbefales ofte å unngå å analysere (og pipe) utgangen frals
fordi problemene kan skjules akkurat der du ikke tenker på … - @Hastur Du ‘ er riktig , i prinsippet, og den berømte siden om don ‘ t parse ls viser ytterligere problemer (og løsninger) når du gir patologiske filnavn. Men den beste måten å håndtere det på er å unngå å ha patologiske filnavn (doh!); og hvis du kan ‘ t, eller hvis du må være robust mot dem, så bruk enten
find
eller – muligens bedre – bruk et kraftigere språk ennsh
for å administrere dem (det faktum atsh
kan alt betyr ikke ‘ t at det ‘ er det beste valget i hvert tilfelle). Skallet er designet for brukervennlighet først. - Jeg er i prinsippet enig i brukervennligheten, men denne varianten mislykkes når du har et filnavn med hver ny linje inne. Dette kan lett skje ubemerket, for eksempel når du kopierer og limer inn en linje fra en pdf i et GUI, så du tenker bare å unngås patologiske filnavn .
- Videre IMHO Det er ‘ det er lett å begynne å analysere
ls
, men det er mange fremtidige problemer. Ofte lager vi skript som vi vil bruke senere, når vi allerede vil glemme grensen deres … (det ‘ s menneskelig, det ‘ er vanlig). Jeg foreslo etfind
eksempel (med-exec
og uten rør) selv om jeg anser det som et bedre (fordi rent skall) svarer cuonglm ‘ s en , solid og posix-kompatibel. - Dette er ganske mye det jeg ‘ d gjorde hvis jeg av en eller annen grunn ønsket å fjerne stripen
.png
suffiks fra en liste over filnavn.Jeg ville ikke ‘ ikke satt det i et skript; i stedet skrev jeg ‘ bare kommandoen ved shell-ledeteksten. Å gjøre det ville være en påminnelse om at jeg ‘ m antar » sunn » filnavn. Det er mange ting jeg ‘ vil gjøre i en engangs manuell kommando, når jeg gjerne tar antagelser om hva ‘ i den nåværende katalogen, at jeg sannsynligvis ikke ville ‘ ikke gjøre det i et skript som kan brukes på nytt i en annen sammenheng.
Svar
Jeg vil gå til basename
(forutsatt GNU-implementering):
basename --suffix=.png -- *.png
Kommentarer
- Merk at hvis du vil bruke den i et rør, kan det være nyttig å bruke GNU-basenavn ‘ s
-z
(eller--zero
) alternativ for å produsere NUL-atskilt (i stedet for nylinjeseparert ) output.
Svar
Du kan bare bruke BASH-kommandoer til å gjøre det (uten eksterne verktøy).
for file in *; do echo "${file%.*}"; done
Dette er nyttig når du «er uten / usr / bin og fungerer fint for filnavn l like this.is.image.png og for alle utvidelser.
Svar
var ikke det nok?
ls -1 | sed "s/\.png//g"
eller generelt, dette
ls -1 | sed "s/\.[a-z]*//g"
fjerner alle utvidelser
Kommentarer
- Det var, men de andre løsningene fungerer også.
- Alt Unix / Unix Like-system har (eller burde ha)
sed
installert ettersom det er et obligatorisk verktøy av standarden. - Faktisk, men
ls
gjør det uansett uten det alternativet når utgangen ikke er en terminal, som er tilfelle her. - Advarsel
ls -1 | sed 's/\.[a-z]*//g'
mislykkes hvis det er et filnavn somImage.png.jpg.png
kutter hele tiden nøkkelen (.png
). Under Unix er tillatt rare filnavn somThe new art of working on .png?files and other formats.png
der?
er en ny linjekarakter. Dessverre vil all løsningen som bare vil pipe / analyserels
-utdata påføre proble ms administrerer slike saker … - Hvorfor
g
kvalifiseringen? Du vil fjerne\.png
bare på slutten av linjen, ikke hver gang den vises.
Svar
Det er ikke trygt å analysere ls
eller å pipe find
[ 1 , 2 ]
Det er ikke trygt å analysere (og til rør) utgangen av ls
eller find
, hovedsakelig fordi det er mulig å finne i filnavnene ikke vanlige tegn som newline , tab … Her vil en ren skallsyklus fungere [ cuonglm ] .
Selv find
-kommandoen ikke piped med alternativet -exec
fungerer:
find ./*.png -exec basename {} .png \;
Oppdateringer / notater : Du kan bruke find .
til å søke selv etter de skjulte filene, eller find ./*.png
å få bare de ikke skjulte. Med find *.png -exec ...
kan du få problemer i tilfelle det var en fil med navnet .png
fordi find vil få det som et alternativ. Du kan legge til -maxdepth 0
for å unngå å komme ned i kataloger som heter Dir_01.png
, eller find ./*.png -prune -exec ...
maks dybde er ikke tillatt (takk Stéphane). Hvis du vil unngå å liste disse katalogene, bør du legge til alternativet -type f
(som også vil ekskludere andre typer ikke-vanlige filer). Ta en titt på man
for et mer komplett panorama om alle tilgjengelige alternativer, og husk å sjekke når de er POSIX-kompatible, for bedre portabilitet.
Noen ord mer
Det kan for eksempel skje at kopiering av tittelen fra et dokument og liming inn i filnavnet, en eller flere nye linjer vil fullføres i selve filnavnet.Vi kan til og med være så uheldige at en tittel kan inneholde til og med nøkkelen vi må bruke like før en ny linje:
The new art of working on .png files and other formats.
Hvis du vil teste, kan du lag filnavn som dette med kommandoene
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
sender ut ?
i stedet for ikke-utskrivbare 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 tilfeller vil du rør utgangen av ls
eller find
følgende kommando vil ikke ha noe hint å forstå hvis den nåværende linjen kommer fra et nytt filnavn eller hvis det følger et ny linje -tegn i presedens filnavn . Et stygt navn, men fortsatt et lovlig navn.
En skallsyklus med et skall Parameter-utvidelse, ${parameter%word}
, i begge varianten med printf
eller echo
fungerer [ cuonglm ], [ Anthon1 ] .
for f in *.png; do printf "%s\n" "${f%.png}" ; done
Fra mannssiden av Shell Parameter-utvidelsen [ 3 ]
$ {parameter% word}
$ {parameter %% word}… resultatet av utvidelsen er verdien av parameteren med det korteste matchende mønsteret (% -saken) eller lengste matchende mønster (%% saken) slettet.
Kommentarer
- Også resultatene av
find
kommando er litt variabel (for eksempel hvis det er en katalog som heterfiles.png
) - Kjære @BroSlow, da jeg skrev svaret over I prøvde 13 (alle) andre varianter som var til stede i det øyeblikket, ved kommandolinje, i et skript, lansert som argument for en shellinnkallelse. Vennligst gjør det samme og fortell meg om de oppfører seg slik du forventer. Jeg gjorde testene mine med
bash 4.3.11
, dash 0.5.7-4, zsh (når det var nødvendig) 5.0.2. Les gjerne dette innlegget som legger til noe mer. Jeg er enig i merknaden om piping utgangen avfind
, for dette
, og jeg skrev i tittelen.:-)
.
ls
er det ingen ting overhodet når utdataene røres eller omdirigeres, men som nevnt i wiki fungerer det kanskje ikke for alle. De fleste vil bare sette inn ?
i stedet for spesialtegn når utgangen sendes til terminalen. dvs. Gjør echo *.png | od -c
og ls *.png | od -c
. Nylinjeproblemet er ikke et problem med ls
, det ‘ er et problem med en hvilken som helst kommando som ikke ‘ t null avsluttes over begge sider av røret. printf "${f%.png}\n"
er feil. Det første argumentet er formatet. Du bør ikke ‘ ikke bruke variable data der inne. Kan til og med sees som et DoS-sårbarhet (prøv med en %1000000000s.png
-fil for eksempel). find ./*.png -prune -exec...
eller du ‘ d har problemer med filnavn som starter med -
(og filer av typekatalog, merk at -maxdepth
ikke er bærbar) Svar
Bruk rev
:
ls -1 | rev | cut -f 2- -d "." | rev
rev
reverserer alle strenger (linjer); du klipper alt etter den første «.» og rev reverserer resten.
Hvis du vil grep
«alma»:
ls -1 | rev | cut -f 2- -d "." | rev | grep "alma"
Kommentarer
-
-1
er ikke nødvendig, som standard her. - Dette mislykkes dårlig i en fil som heter
My.2016.Summer.Vacation.png
- @DavidConrad min dårlige: / Jeg har korrigert til
cut -f 2-
- Nå fungerer den med den filen, men ennå ikke med en fil med
.png
og en ny linje like etter … Det anbefales å unngå å analyserels
fordi det elsker å gjemme overraskelsene godt … 🙂
Svar
Hvis jeg visste at katalogen bare hadde filer med .png som utvidelse, hadde jeg nettopp kjørt: ls | awk -F. "{print $1}"
Dette returnerer det første «feltet» for alt der det er et filnavn. utvidelse.
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
- Dessverre vil det mislykkes på alle filnavnene med mer enn ett
.
, somImage.1.png
og til og med på de med ikke hyggelig navn , med spesialtegn inni. som den nye linjen eller den du vil bruke som (inngangs) opptaksseparator iawk
,RS
. Det anbefales å unngå å analyserels
-utgangen fordi den elsker å skjule et problem som vil oppstå når du ikke forventer. Du kan lese mer i referansen 1 eller 2 . BTW hyggelig ideen om å bruke awk … Jeg la noen eksempler i ett svar. - Det er sant, men gitt eksemplet fra Colin, ville det fungere helt fint. For å få det til å fungere for saken du foreslo, ville jeg ‘ sannsynligvis endre den til: [rsingh @ rule51 TESTDIR] $ ls | sed -e ‘ s / .png $ // ‘ 10 1 2 3 4 5 6 7 8 9 harry.the.bunny whats .a.png.filename Ikke prøver å være vanskelig, men gitt Colin ‘ s behov, er jeg ‘ ikke sikker på hva problemet ville analyser ls.
- beklager … Jeg skjønte bare at jeg ikke ‘ ikke viste katalogen med filene før jeg modifiserte utdataene til ‘ 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 whats .a.png.filename
- note1 du må unnslippe
.
i\.
inne ised -e 's/\.png$//'
, men så blir det et svar som bare er skrevet. 🙁 note2 du kan prøve å brukeawk
med noe sånt somls | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}'
… men du vil ha alltid problemet som awk ikke kan vite om linjen ankommer følger eller ikke en ny linje i filnavnet. Jeg prøvde å si bedre i svaret mitt. - Takk Hastur, jeg savnet det :). Jeg dro også bruken av awk til fordel for sed i dette tilfellet.
Svar
i henhold til din kommentar «Jeg har en tekstfil hvor alle navnene er oppført uten utvidelsen. Jeg vil lage et PHP-skript som sammenligner tekstfilen med mappen for å se hvilken fil som 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øyaktige metoden som fremhevet av @roaima. Uten de rømte \.png
filene kalt a_png.png
vil være oppført som: a_
.
Kommentarer
- ved hjelp av
ls -l
, som du gjør, gir filopplysningene, det er ikke det OP spurte om.
Svar
En enkel skalllinje (ksh, bash eller zsh; ikke dash):
set -- *.png; printf "%s\n" "${@%.png}"
En enkel funksjon (fra Ingen utvidelse):
ne(){ set -- *.png; printf "%s\n" "${@%.png}"; }
Eller en funksjon som fjerner hvilken som helst utvidelse gitt (png som standard):
ne(){ ext=${1:-png}; set -- *."$ext"; printf "%s\n" "${@%.${ext}}"; }
Bruk som:
ne jpg
Hvis utgangen er en stjerne *
, finnes det ingen fil med den utvidelsen.
Svar
Du kan prøve følgende feed awk resultatet av ls superatøren din er «.» og siden alle filene dine vil ha name.png skriver du ut den første kolonnen:
ls | awk -F"." "{print $1}"
Svar
Hvis du har tilgang til sed, er dette bedre da det vil fjerne den siste filtypen, uansett hva den er (png, jpg, tiff, etc …)
ls | sed -e "s/\..*$//"
Kommentarer
- Bryter for filnavn som
this.is.a.dotty.txt
. Prøvs/\.[^.]*$//
i stedet.
.
i dem. Selv om konvensjonen sier å navngi filene dine med.png
på slutten, er det ingen grunn til at jeg ‘ ikke kan ha en png-fil som heterfoo.zip
ellermy.picture.20160518
eller baremypic
.ls
og for å pipe utgangen tills
ogfind
, hovedsakelig fordi muligheten til å pådra seg inewline
,` tab char i filnavnet. Hvis filnavnet erThe new art of working on .png\NEWLINE files and other formats
, vil mange av løsningsforslaget skape problemer.