ls -1 elenca i miei elementi in questo modo:
foo.png bar.png foobar.png ...
Voglio che sia elencato senza .png in questo modo:
foo bar foobar ...
(la directory contiene solo .png file)
Qualcuno può dirmi come usare grep in questo caso?
Scopo: ho un file di testo in cui tutti i nomi sono elencati senza il estensione. Voglio creare uno script che confronti il file di testo con la cartella per vedere quale file manca.
Commenti
Risposta
Hai solo bisogno della shell per questo lavoro.
POSIZIONARE:
for f in *.png; do printf "%s\n" "${f%.png}" done
Con zsh:
print -rl -- *.png(:r)
Commenti
- Là ‘ non è necessario
printf;echo ${f%.png}sarà sufficiente. - @Conrad: luso di echo non ha ‘ funzionato correttamente in alcuni casi, se il nome del file iniziare con un trattino o contenere sequenze di escape.
- @DavidConrad: vedere anche unix.stackexchange.com/a/65819/38906
- @DavidConrad Inoltre, credo che printf sia integrato, proprio come echo, qualcuno mi corregge se ‘ sbaglio
Risposta
ls -1 | sed -e "s/\.png$//"
Il comando sed rimuove (ovvero, sostituisce con la stringa vuota) qualsiasi stringa .png trovata alla end di un nome file.
Il . è sottoposto a escape come \. in modo che venga interpretato da sed come carattere letterale . anziché come espressione regolare . (che significa che corrisponde a qualsiasi ch carattere). $ è lancora di fine riga, quindi “non corrisponde a .png nel mezzo del nome di un file.
Commenti
- Penso che lOP voglia rimuovere qualsiasi estensione, ma probabilmente solo ” last one “. Quindi forse modifica la tua risposta altrimenti valida con:
sed 's/\.[^.]*$//' - sì, quella regexp lo farebbe funziona in quel caso … ma se lOP lo vuole, dovrebbe dirlo invece di dire specificamente che ” lo vuole elencato senza il .png ”
-
-1non è necessario, essendo limpostazione predefinita qui. - @jlliagre Sono daccordo con cas che
-1dovrebbe essere specificato. ‘ è solo limpostazione predefinita quando pipe è acceso, il che è una sorpresa nascosta per alcuni. Quindi renderlo esplicito aiuta Lo faccio anche nei miei script, quindi so che tipo di o utput Mi ‘ mi aspetto. - Avviso Nel caso di un nome file con la chiave (
.png) prima di un carattere di nuova riga cancellerai anche quel.pnge non solo lultimo. È meglio evitare di pipe e analizzare loutput di ls, che riserva spesso sorprese ben nascoste … (alcune parole e riferimenti in più nella risposta).
Risposta
Se vuoi solo usare bash:
for i in *; do echo "${i%.png}"; done
Dovresti cercare grep quando cerchi di trovare corrispondenze, non per rimuovere / sostituire quello che sed è più appropriato:
find . -maxdepth 1 -name "*.png" | sed "s/\.png$//"
Una volta deciso che è necessario creare alcune sottodirectory per mettere ordine nei file PNG, puoi facilmente cambiarlo in:
find . -name "*.png" | sed "s/\.png$//"
Commenti
- ls -1 | sed ‘ s / .png // ‘ funziona alla grande. Grazie!
- La soluzione
findpiped asedpuò presentare alcuni problemi se trovi un file con la chiave (.png) come parte del nome e appena prima di un carattere di nuova riga. È meglio evitare di pipe e analizzare loutput difindols, riserva spesso sorprese ben nascoste … (alcune parole e riferimenti più nella risposta). - Probabilmente sostituire
findcon qualcosa comeechonellultimo esempio. Non è chiaro quale sia lo scopo difinde i risultati dipendono dalla struttura della directory (ad esempio, se hai una directoryfiles.png) - @BroSlow Aggiornato a qualcosa di più sensato.
Rispondi
Unaltra risposta molto simile (sono “sorpreso di questo una variante particolare non è ancora apparsa) è:
ls | sed -n "s/\.png$//p"
- Non è necessario
-1opzione als, poichélspresuppone che se loutput standard non è “un terminale (in questo caso” una pipe). - lopzione
-npersedsignifica “non stampare la riga per impostazione predefinita” - lopzione
/palla fine della sostituzione significa “… e stampa questa riga se è stata effettuata una sostituzione”.
La rete leffetto di ciò è stampare solo quelle righe che terminano con .png, con rimosso. Cioè, questo soddisfa anche la leggera generalizzazione della domanda dellOP, dove la directory non “contiene solo .png file.
Il sed -n è spesso utile nei casi in cui potresti altrimenti usare grep + sed.
Commenti
- Mi piace come la cura hai usato per scrivere la tua risposta. Questa soluzione presenterà problemi con i nomi dei file inclusi newline , non stamperà la prima parte del nome. Ancor di più seèpiù cattiva con la chiave (
.png) prima del carattere di nuova riga: in tal caso stamperai quella parte senza png, non cancellando solo lultima parte. È spesso suggerito per evitare di analizzare (e reindirizzare) loutput dilsperché i problemi possono essere nascosti proprio dove non stai pensando … - @Hastur Tu ‘ hai corretto , in linea di principio, e la famosa pagina su don ‘ t parse ls elenca ulteriori problemi (e soluzioni) quando si consegnano nomi di file patologici. Ma il modo migliore per gestirlo è evitare di avere nomi di file patologici (doh!); e se puoi ‘ t, o se devi essere robusto contro di loro, allora usa
findo – forse meglio – usa un linguaggio più potente dishper gestirli (il fatto cheshpuò fare tutto non ‘ t significa che ‘ è la scelta migliore in ogni caso). La shell è progettata innanzitutto per lusabilità. - Sono daccordo, in linea di principio, sullusabilità, ma questa variante fallisce quando hai un nome file con ogni nuova riga allinterno. Questo può facilmente accadere inosservato, ad esempio, quando copi e incolli una riga da un pdf in una GUI, quindi pensi solo che siano evitati nomi di file patologici.
- Inoltre IMHO È ‘ facile iniziare ad analizzare
ls, ma è alle porte di problemi futuri. Spesso creiamo script che useremo in seguito, quando già dimenticheremo il loro limite … (è ‘ umano, ‘ è normale). Ho proposto unfindesempio (con-exece senza pipe) anche se ritengo una migliore (perché pura shell) risponda alla cuonglm ‘ s una , solida e conforme a posix. - Questo è più o meno quello che ‘ farei se, per qualche motivo, volessi rimuovere il
.pngsuffisso da un elenco di nomi di file.Non ‘ lo metterei in uno script; invece ‘ digito semplicemente il comando al prompt della shell. In questo modo mi ricorderei che ‘ m assumendo ” sano di mente ” nomi di file. Ci sono molte cose che ‘ farò in un comando manuale una tantum, quando mi sento libero di fare supposizioni su cosa ‘ nella directory corrente, cosa che probabilmente non ‘ farei in uno script che potrebbe essere riutilizzato in un altro contesto.
Risposta
Preferisco basename (assumendo limplementazione GNU):
basename --suffix=.png -- *.png
Commenti
- Nota che se vuoi usarlo in una pipe, potresti trovare utile usare GNU basename ‘ s
-z(o--zero) per produrre valori separati da NUL (anziché separati da nuova riga ).
Risposta
Puoi usare solo comandi BASH per farlo (senza strumenti esterni).
for file in *; do echo "${file%.*}"; done
Questo è utile quando sei senza / usr / bin e funziona bene per i nomi di file l come this.is.image.png e per tutte le estensioni.
Risposta
“non era abbastanza?
ls -1 | sed "s/\.png//g"
o in generale, questo
ls -1 | sed "s/\.[a-z]*//g"
rimuoverà tutte le estensioni
Commenti
- Lo era, ma funzionano anche le altre soluzioni.
- Tutti i sistemi Unix / Unix Like hanno (o dovrebbero avere)
sedinstallato poiché è unutilità obbligatoria secondo lo standard. - Effettivamente, ma
lslo fa comunque senza questa opzione quando il suo output non è un terminale, come è il caso qui. - Avviso
ls -1 | sed 's/\.[a-z]*//g'non funzionerà se è presente un nome file comeImage.png.jpg.pngtagliando continuamente la chiave (.png). In Unix sono consentiti strani nomi di file comeThe new art of working on .png?files and other formats.pngdove?è un carattere di nuova riga. Sfortunatamente tutta la soluzione che semplicemente reindirizzerà / analizzerà loutput dilsincorrerà in problemi ms gestire tali casi … - Perché il qualificatore
g? Vuoi rimuovere\.pngsolo alla fine della riga, non ogni volta che appare.
Risposta
Non è sicuro analizzare ls o reindirizzare find [ 1 , 2 ]
Non è sicuro analizzare (e reindirizzare) loutput di ls o find, principalmente perché è possibile trovare nei nomi di file caratteri non usuali come la nuova riga , la scheda … Qui un ciclo di shell puro funzionerà [ cuonglm ] .
Anche il comando find non convogliato con lopzione -exec funzionerà:
find ./*.png -exec basename {} .png \;
Aggiornamenti / Note : puoi utilizzare find . per cercare anche i file nascosti oppure find ./*.png per ottenere solo quelli non nascosti. Con find *.png -exec ... puoi avere problemi nel caso fosse presente un file chiamato .png perché find lo otterrà come opzione. Puoi aggiungere -maxdepth 0 per evitare di scendere in directory denominate Dir_01.png o find ./*.png -prune -exec ... quando maxdepth non è consentito (grazie Stéphane). Se vuoi evitare di elencare quelle directory dovresti aggiungere lopzione -type f (che escluderebbe anche altri tipi di file non regolari). Dai unocchiata al man per un panorama più completo su tutte le opzioni disponibili e ricordati di controllare quando sono conformi a POSIX, per una migliore portabilità.
Qualche parola in più
Può accadere, ad esempio, che copiando il titolo da un documento e incollandolo nel nome del file, uno o più newline finiscano nel nome del file stesso.Possiamo anche essere così sfortunati che un titolo possa contenere anche la chiave che dobbiamo usare appena prima di una nuova riga:
The new art of working on .png files and other formats.
Se vuoi provare, puoi creare nomi di file come questo con i comandi
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"
Il semplice /bin/ls *png restituirà ? invece dei caratteri non stampabili
A file with two lines?and This is the second.png The new art of working on .png?files and other formats.png
In tutti i casi in cui indirizza loutput di ls o find il seguente comando non avrà alcun suggerimento da capire se la riga attuale proviene da un nuovo nome file o se segue un carattere nuova riga nel precedente nome file . Un nome brutto in effetti, ma ancora legale.
Un ciclo di shell con unespansione dei parametri della shell, ${parameter%word}, in entrambi la variante con printf o echo funzionerà [ cuonglm ], [ Anthon1 ] .
for f in *.png; do printf "%s\n" "${f%.png}" ; done
Dalla pagina man dellespansione dei parametri della shell [ 3 ]
$ {parametro% parola}
$ {parametro %% parola}… il risultato dellespansione è il valore del parametro con il modello di corrispondenza più breve (il caso %) o il modello di corrispondenza più lungo (il caso %%) eliminato.
Commenti
- Anche i risultati del tuo
findsono un po variabili (ad esempio se cè una directory chiamatafiles.png) - Gentile @BroSlow, quando ho scritto la risposta sopra io provato 13 (tutte) delle altre varianti presenti in quel momento, da riga di comando, in uno script, lanciato come argomento di una invocazione di shell. Per favore, fai lo stesso e dimmi se si comportano come ti aspetti. Ho eseguito i miei test con
bash 4.3.11, trattino 0.5.7-4, zsh (quando necessario) 5.0.2. Sentiti libero di leggere questo post che aggiunge qualcosa in più. Sono daccordo sulla nota di piping loutput difind, per questo ho espressamente suggerito-exece ho scritto nel titolo.:-). - Rileggi di nuovo il wiki. Penso ancora che tu debba reindirizzare nel tuo esempio, dal momento che ‘ è ciò che ‘ viene discusso qui. E per la maggior parte delle versioni moderne di
lsnon cè alcun problema quando loutput viene reindirizzato o reindirizzato, ma come menzionato in wiki potrebbe non funzionare per tutti. La maggior parte inserirà solo?al posto di caratteri speciali quando loutput viene inviato al terminale. ad es.echo *.png | od -cels *.png | od -c. Il problema di nuova riga non è un problema conls, è ‘ è un problema con qualsiasi comando che non ‘ t terminare null su entrambi i lati del pipe. -
printf "${f%.png}\n"è sbagliato. Il primo argomento è il formato, non dovresti ‘ utilizzare dati variabili al suo interno. Può anche essere vista come una vulnerabilità DoS (prova con un%1000000000s.pngfile per esempio). - Tu ‘ d è necessario
find ./*.png -prune -exec...o ‘ hai problemi con nomi di file che iniziano con-(e file di type directory, nota che-maxdepthnon è portabile)
Rispondi
Utilizza rev:
ls -1 | rev | cut -f 2- -d "." | rev
rev inverte tutte le stringhe (linee); hai tagliato tutto dopo il primo “.” e rev ripristina il resto.
Se desideri grep “alma”:
ls -1 | rev | cut -f 2- -d "." | rev | grep "alma"
Commenti
-
-1non è necessario, essendo limpostazione predefinita qui. - Questo non funziona correttamente su un file denominato
My.2016.Summer.Vacation.png - @DavidConrad mio male: / ho corretto a
cut -f 2- - Ora funziona con quel file ma non ancora con un file con
.pnge una nuova riga subito dopo … Si consiglia di evitare di analizzarelsperché ama nascondere bene le sorprese … 🙂
Answer
Se avessi saputo che la directory avesse solo file con estensione .png, avrei semplicemente eseguito: ls | awk -F. "{print $1}"
Questo restituirà il primo “campo” per qualsiasi cosa in cui sia presente un nomefile.eestensione.
Esempio:
[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
Commenti
- Sfortunatamente fallirà su tutti i nomi di file con più di un
., comeImage.1.pnge anche su quelli con non carino nomi , con caratteri speciali allinterno. come la nuova riga o quella che utilizzerai come separatore di record (input) inawk,RS. Si consiglia di evitare di analizzare loutputlsperché ama nascondere i problemi che sorgeranno quando non te lo aspetti. Puoi leggere di più in quelli di riferimento 1 o 2 . Comunque bella lidea di usare awk … ho messo alcuni esempi in una risposta. - Vero, tuttavia, dato lesempio fornito da Colin, funzionerebbe benissimo. Per farlo funzionare nel caso che hai suggerito, ‘ probabilmente lo cambierei in: [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 Non sto cercando di essere difficile, ma dato il ‘ bisogno di Colin, ‘ non sono sicuro di quale sarebbe il problema sta analizzando ls.
- scusa … mi sono appena accorto di non ‘ mostrare la directory con i file prima di sed modificare loutput di ‘ 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 devi eseguire lescape da
.in\.allinterno delsed -e 's/\.png$//', ma così diventa una risposta appena scritta. 🙁 note2 puoi provare a utilizzareawkcon qualcosa comels | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}'… ma avrai sempre il problema che awk non può sapere se la linea sta arrivando sta seguendo o meno una nuova riga allinterno del nome del file. Ho cercato di dire meglio nella mia risposta. - Grazie Hastur, mi sono perso :). Inoltre, ho abbandonato luso di awk a favore di sed in questo caso.
Answer
secondo il tuo comment “Ho un file di testo in cui sono elencati tutti i nomi senza lestensione. Voglio creare uno script PHP che confronti il file di testo con la cartella per vedere quale file manca”:
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
e viceversa:
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)
Risposta
ls -l | sed "s/\.png$//"
È il metodo più accurato come evidenziato da @roaima. Senza i \.png file con escape denominati a_png.png verrebbero elencati come: a_.
Commenti
- utilizzando
ls -l, come fai, fornisce i dettagli del file, che non è ciò che lOP ha chiesto circa.
Risposta
Una semplice riga di shell (ksh, bash o zsh; non trattino):
set -- *.png; printf "%s\n" "${@%.png}"
Una semplice funzione (da Nessuna estensione):
ne(){ set -- *.png; printf "%s\n" "${@%.png}"; }
O una funzione che rimuove qualsiasi estensione fornita (png per impostazione predefinita):
ne(){ ext=${1:-png}; set -- *."$ext"; printf "%s\n" "${@%.${ext}}"; }
Utilizza come:
ne jpg
Se loutput è un asterisco *, non esiste alcun file con tale estensione.
Risposta
Puoi provare il seguente feed awk loutput di ls il tuo superatore è “.” e poiché tutti i tuoi file avranno name.png, stampa la prima colonna:
ls | awk -F"." "{print $1}"
Answer
Se hai accesso a sed, è meglio perché rimuoverà lultima estensione del file, non importa quale sia (png, jpg, tiff, ecc …)
ls | sed -e "s/\..*$//"
Commenti
- Interruzioni per nomi di file come
this.is.a.dotty.txt. Prova inveces/\.[^.]*$//.
.al loro interno. Sebbene la convenzione stabilisca di denominare i file con.pngalla fine, non cè motivo per cui ‘ non abbia un file png denominatofoo.zipomy.picture.20160518o semplicementemypic.lse per reindirizzare loutput dilsefind, principalmente perché la possibilità di incorrere innewline,` tab char nel nome del file. Se il nome del file èThe new art of working on .png\NEWLINE files and other formatsmolte delle soluzioni proposte creeranno problemi.