2011-12-27 10 views
17

codice successivo non funziona a causa di spazi nei nomi di file, Come risolvere?per nome in `ls` e nomi di file con spazi

IFS = '\n' 
for name in `ls ` 
do 
    number=`echo "$name" | grep -o "[0-9]\{1,2\}"` 
    if [[ ! -z "$number" ]]; then 
     mv "$name" "./$number" 
    fi 
done 
+2

Vedere http://mywiki.wooledge.org/ParsingLs#line-75 – user123444555621

risposta

22

Basta non utilizzare la sostituzione di comando: utilizzare for name in *.

+0

Si noti che questo potrebbe non riuscire in una directory vuota. Il ciclo verrà eseguito una volta con 'name =" * "'. Non è un problema in questo caso particolare però. – user123444555621

+0

Se risulta essere un problema, 'shopt -s nullglob' causerà l'estensione di * * a zero parole se non ci sono corrispondenze. – ephemient

12

Sostituire

 
for name in `ls` 

con:

 
ls | while read name 

Avviso: bash scoping variabile è terribile. Se cambi una variabile all'interno del ciclo, non avrà effetto al di fuori del ciclo (nella mia versione non lo farà, nella tua versione lo farà). In questo esempio, non importa.

Avviso 2: funziona per nomi di file con spazi, ma non riesce per alcuni nomi di file strani ma validi. Vedi il commento di Charles Duffy sotto.

+0

"Se si modifica una variabile all'interno del ciclo, non avrà effetto al di fuori del ciclo Se si modifica una variabile all'interno del ciclo, non avrà effetto al di fuori del ciclo" - se si utilizza il costrutto, sì, perché qualunque sia è dopo che la pipe è stata lanciata in una subshell. Si prevede pertanto che abbia un ambito variabile diverso. – fge

+0

Penso che il comportamento di bash qui sia irregolare. Se lo capisci, e sembra che tu (es. Fge) fai, allora sai cosa aspettarti. Ma l'ho imparato nel modo più duro, mi sembra ancora strano. – ugoren

+0

'ls | mentre read name è sbagliato. Non gestisce correttamente i nomi di file con letterali backslash, o nomi di file con newline letterali, o nomi di file con spazi iniziali o finali. –

3

assomiglia due potenziali problemi:

In primo luogo, la variabile IFS ed è l'assegnazione non dovrebbe avere spazio in loro. Invece di

IFS = '\n' dovrebbe essere IFS=$'\n'

In secondo luogo, for name in ls causerà problemi con il nome del file che ha spaces e newlines. Se hai appena desidera gestire filename con spaces poi fare qualcosa di simile

for name in *

Non capisco il significato della linea

number=`echo "$name" | grep -o "[0-9]\{1,2\}"` 

Questo vi darà numeri trovati in filename with spaces in new lines . Potrebbe essere quello che vuoi

+0

In realtà, dovrebbe essere 'IFS = $ '\ n'' - senza' $ ',' \ n' non viene interpretato come una nuova riga, ma come letterale barra rovesciata e la lettera "n". –

+0

Oops ... buona cattura, corretto. Grazie Gordon. :) –

Problemi correlati