Lo spazio non è consentito in un nome file?


31

Si dice che su Unix e Linux in generale, si dovrebbe evitare di avere spazi in un nome file di un file (file ordinario, dir, collegamento, file del dispositivo, ...).

Ma lo faccio sempre. Per un nome file con uno spazio all'interno,

  • In Nautilus, il personaggio spaziale viene mostrato come spazio.
  • Nel terminale Bash, utilizzo o \ per rappresentare uno spazio, oppure racchiudo il nome file tra una coppia di virgolette.
  • nei file di alcune applicazioni (Nautilus, non sono sicuro che anche il SO lo farà), il nome del file viene scritto con lo spazio sostituito con %20.

Uno spazio non è davvero consentito in un nome file?

Come usi o gestisci correttamente uno spazio in un nome file?


17
È permesso ma è davvero, davvero fastidioso. Non c'è motivo per questo. Non farlo
Lightness Races with Monica

3
Puoi anche creare un file chiamato -rf ~(usa touch -- "-rf ~"), ma non lo consiglierei.
Ian D. Scott,

5
Puoi farlo, è permesso, come creare uno script autodistruggente chiamato "cd" ma non dovresti farlo. Il tuo file ha già un aspetto diverso in 3 diversi strumenti, non è poi così male?
Falco,

7
Non tutti condividono l'opinione che sia davvero, davvero fastidioso. E "Non c'è motivo per questo" è così ovviamente falso che non ha bisogno di essere confutato. Anni fa mi sono arreso e ho imparato a gestire correttamente gli spazi, e per la maggior parte non è un grosso problema.

2
Gli spazi di @snailboat sono un sintomo del vero problema che è una mancanza di standardizzazione. I filesystem Unix consentono "nomi" di file a BLOB binari quasi illimitati. Gli unici byte illegali sono 0 e 47 (il /separatore). L'uso di tutti i 254 byte rimanenti apre le porte a tutti i modi di indicibili "nomi" di eldritch. Ovviamente questo è folle, ma non tutti sono d'accordo su cosa sia "sano", e personaggi diversi romperanno strumenti diversi. L'intersezione della sanità mentale di tutti è piuttosto piccola .
jw013,

Risposte:


48

Gli spazi, e in effetti tutti i personaggi tranne /e NUL, sono ammessi nei nomi dei file. La raccomandazione di non utilizzare gli spazi nei nomi dei file deriva dal pericolo che possano essere interpretati erroneamente da un software che li supporta male. Probabilmente, tale software è difettoso. Ma anche discutibilmente, i linguaggi di programmazione come lo script di shell rendono fin troppo facile scrivere software che si rompe quando viene presentato con nomi di file con spazi, e questi bug tendono a sfuggire perché gli script di shell non sono spesso testati dai loro sviluppatori usando nomi di file con spazi in loro.

Gli spazi sostituiti con %20non si vedono spesso nei nomi dei file. Viene utilizzato principalmente per gli URL (web). Anche se è vero che la codifica% dagli URL a volte si fa strada nei nomi dei file, spesso per caso.


6
È "codifica URL" o "codifica percentuale" en.wikipedia.org/wiki/URL_encoding Secondo il fatto che il nome più appropriato è probabilmente "codifica URI", ma la gente trova l' URL più facile da dire dell'URI , quindi questa è una forma comune di termine improprio. Si noti che l'insieme di caratteri riservati negli URI è più grande di quanto non sia per i nomi di file * nix.
Riccioli d'oro

1
@Tim Non so che puoi specificare un carattere NUL in qualsiasi argomento della riga di comando in bash. Ho provato alcune cose come citarlo con Ctrl-V e qualcosa del genere $(echo -e \\0)ma non ha funzionato. Il fatto è che il motivo per cui NUL non può essere utilizzato nei nomi di file è che non può essere utilizzato nelle stringhe C (perché è il terminatore di stringhe) e tutte le API sottostanti e praticamente tutte le stringhe gestite dai programmi C usano quel formato . Poiché bashè scritto in C, potrebbe semplicemente non avere alcun supporto per tutte le stringhe con NUL in esse. Potrei sbagliarmi, potrebbe esserci un modo oscuro ...
Celada,

1
L'ordinamento dipende dal contesto. Le funzioni di stringa generalmente non contano il null finale (o meglio, il primo null è la fine della stringa, anche se c'è roba dopo), quindi in questo senso ha lunghezza zero e quindi sarebbe considerato vuoto.
Riccioli d'oro

3
@Celada ovviamente puoi usare NULe bash, ti serve $'\0'. Ad esempio:find . -print0 | while read -d $'\0' f; do echo "$f"; done
terdon

1
@goldilocks Le persone in realtà pronunciano l'URL come 'url', approssimativamente facendo rima con 'earl'?
Miles Rout

17

Gli spazi sono ammessi nei nomi dei file, come hai osservato.

Se guardi la voce "maggior parte dei filesystem UNIX" in questo grafico in Wikipedia , noterai:

  • È consentito qualsiasi set di caratteri a 8 bit. Possiamo anche sottoporre a ASCII a 7 bit anche sotto questo ombrello, poiché è un sottoinsieme di vari set a 8 bit ed è sempre implementato usando byte a 8 bit.

  • Gli unici personaggi proibiti sono /e "null". "Null" si riferisce a un byte zero, ma questi non sono comunque consentiti nei dati di testo.

Tuttavia , se si utilizza la shell, è possibile rendersi conto che ci sono alcuni personaggi che creeranno una seccatura, soprattutto *, che è un operatore di globbing POSIX.

A seconda di come si desidera definire "seccatura", è possibile includere spazi bianchi (spazi, tabulazioni, nuove righe, ecc.), In quanto ciò crea la necessità di quotare "". Ma questo è inevitabile, dal momento che gli spazi sono ammessi, quindi ...

Come usi o gestisci correttamente uno spazio in un nome file?

In un contesto di shell / riga di comando, racchiudi il nome del file tra virgolette singole o doppie (ma nota che non sono gli stessi altri problemi WRT), oppure evita gli spazi con \, ad esempio:

> foo my\ file\ with\ spaces\ in\ the\ name

1
Come si specifica il carattere NUL in bash? Voglio testarlo in un nome file.
Tim

1
Non puoi. "Esegui semantica" si riferisce al fatto che in C (e in ogni altra lingua di cui sono a conoscenza), le stringhe di testo sono nulle. La shell è implementata in C. La cosa più subdola che mi viene in mente è touch $(echo -e "foo\00bar")- i -eprocessi \0Ncome un valore ottale, ma si perde ancora da qualche parte, in quanto crea un file chiamato foobar. Naturalmente NULL non è stampabile, ma garantisco che è passato da lì a causa della restrizione della stringa C.
Riccioli d'oro

"le stringhe di testo sono nulle" -> Per chiarire ulteriormente: le stringhe sono sempre memorizzate con un byte zero alla fine, motivo per cui "non è consentito" nel testo: se ne inserisci una, hai effettivamente terminato la stringa a quel punto. Ad esempio, foo[NULL]barfinirebbe fooper la maggior parte degli intenti e degli scopi. Il fatto che ciò non accada echo -emostra che il NULL è stato eliminato da qualche parte.
Riccioli d'oro

5
La stragrande maggioranza dei linguaggi di programmazione consente caratteri null nelle stringhe. Accade semplicemente che il linguaggio principale che non lo fa sia C, su cui si basa Unix - e la maggior parte delle shell Unix non consente nemmeno caratteri null nelle stringhe. In ogni caso, @Tim, tutte le interfacce Unix usano stringhe con terminazione null, quindi un byte null è l'unica cosa che non puoi mai avere in un nome di file (in più /che è il separatore di directory e non può essere citato, quindi può essere in un percorso ma non in un nome file).
Gilles 'SO- smetti di essere malvagio' il

1
... ma [non importa più]. Non qualcosa che farei troppo spesso, comunque. Secondo me non c'è motivo per loro di essere nei dati testuali. Lo avrei corretto, ma è un commento.
Riccioli d'oro

3

Il motivo è in gran parte storico: WAY indietro nelle nebbie degli spazi temporali non era consentito nei nomi dei file, quindi gli spazi venivano usati come separatori di parole chiave / nome file. I futuri interpreti della shell dovevano essere retrocompatibili con i vecchi script, e quindi siamo bloccati dal mal di testa che abbiamo oggi.

Gli sviluppatori di processi che non hanno molto a che fare con gli umani possono rendere le cose molto, molto più facili, lasciando cadere completamente gli spazi. Apple lo fa, il contenuto di / Sistema / Libreria / CoreServices / contiene pochissimi spazi, i programmi con spazi vengono aperti per conto dell'utente e WouldLookStrangeIfCamelCased. Percorsi simili solo unix evitano anche gli spazi.

(aneddoto in qualche modo correlato: a metà degli anni 90 un drone di Windows ha detto "Nomina una cosa che puoi fare su un Mac che non posso fare su Windows" -> "Usa 12 caratteri in un nome file." -> Silenzio. Gli spazi erano possibile anche in quei 12 caratteri)


1
Usavo V6 Unix (c. 1978). Allora gli spazi erano ammessi. Un compito che avevo era scrivere un programma per analizzare il file system (usando gli I / O diretti del disco) e cercare un file che avesse spazi e backspaces nel suo nome.
Wallyk,

fanno cadere degli spazi del tutto - o i nomi dei file contengono pochissimi spazi?
Mikeserv,

2

Quindi sì, come affermato più volte altrove, un nome file può contenere quasi tutti i caratteri. Ma bisogna dire che un nome file non è un file. Ha un certo peso come attributo di file in quanto in genere è necessario un nome file per aprire un file, ma il nome di un file punta solo al file effettivo. È un collegamento, memorizzato nella directory che lo ha registrato, accanto al numero dell'inode - che è un'approssimazione molto più vicina a un file reale .

Quindi, lo sai, chiamalo come vuoi. Al kernel non importa: tutti i riferimenti ai file che gestirà gestiranno comunque i numeri di inode reali. Il nome del file è una cosa per il consumo umano - se vuoi renderlo pazzo, beh, è ​​il tuo filesystem. Qui, farò alcune cose folli:

Per prima cosa creerò 20 file e li nominerò con nient'altro che spazi, ogni nome file che contiene uno spazio in più rispetto all'ultimo:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

Questo è abbastanza divertente. Guarda il mio ls:

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

Ora rispondo a questa directory:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

Ecco ../mirror/i contenuti:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

Ok, ma forse lo stai chiedendo - ma a che serve? Come puoi sapere quale è quale? Come puoi essere sicuro di aver collegato il numero di inode giusto al nome di file giusto?

Bene...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

PRODUZIONE

heyhey
heyhey

Vedi, sia il numero di inode contenuto in ../mirror/"${tgt%% .*}"che quello a cui fa riferimento si ./' 'riferiscono allo stesso file. Descrivono lo stesso file. Lo chiamano, ma niente di più. Non c'è alcun mistero, in realtà, solo qualche inconveniente che potresti fare per te stesso, ma che alla fine avrà poco o nessun effetto sul funzionamento del tuo filesystem unix.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.