Cosa sono le directory ./ e ../?


20

Domanda semplice, ma non sono sicuro di dove cercare e google non risponde ai periodi e alle barre.

Sto solo provando a contare il numero di file e directory nella directory corrente (senza includere sottocartelle / file) e stavo cercando di differenziare ls -1 | wc -le ls | wc -lpoiché sembrano identici. Un sito che stavo guardando diceva "Tieni presente che questo conta anche le directory ./ e ../." per quanto riguarda quello con ls -1, e non sono sicuro che ciò significhi che include prima le directory o qualcosa del genere (cosa che non voglio), ma non sembra farlo dai test.

Qualcuno potrebbe confermare quale di questi sarebbe il più adeguato per contare # di file e directory solo nella directory corrente (non sottotitoli) e cosa intendono per directory ./ e ../?


Il "Tieni presente che questo conta anche le directory ./ e ../" è sbagliato (a meno che non sia un refuso per "." E "..".
vonbrand

Risposte:


15

Ogni directory su un sistema Unix (e probabilmente anche ogni altro sistema) contiene almeno due voci di directory. Questi sono .(directory corrente) e ..(directory principale). Nel caso della directory principale, questi puntano nella stessa posizione, ma con qualsiasi altra directory, sono diversi. Puoi vederlo da solo usando i comandi stat, pwde cd(su Linux):

$ cd /
$ stat . .. bin sbin | grep Inode
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 548865      Links: 2
Device: 802h/2050d      Inode: 2670593     Links: 2
$ pwd
/
$ cd ..
$ pwd
/
$

Si noti che bine sbinciascuno ha due collegamenti ad esso. Uno è la voce della directory nella directory principale e l'altra è la .voce all'interno di quella directory.

Usare lscon una pipe per wc -lè un semplice trucco per contare il numero di righe nell'output di ls. Il presupposto è che ogni file o directory occuperà esattamente una riga nell'output. GNU, quando l'uscita non è un terminale, lo farà automaticamente; altri potrebbero aver bisogno -1dell'opzione per attivare esplicitamente il comportamento. wc -lconta e genera semplicemente il numero di righe ( -l) nel suo input.

Il problema con questo approccio è che in Linux e sui file system tradizionalmente usati su Linux, i nomi di file e directory (in realtà sono la stessa cosa in questo senso) possono contenere caratteri di nuova riga . In presenza di questi, uno dei due metodi cade a pezzi: quelle voci verranno conteggiate come due o più voci quando in realtà sono una sola.

Finché stai usando GNU ls, non hai voci di directory con nomi contenenti caratteri di nuova riga e non hai alias dispari per ls(ad esempio ls -a), entrambi genereranno il conteggio di file e directory nella directory corrente (o specificata). Per la maggior parte delle persone, questo è abbastanza buono, ma non è valido nel caso generale .

Se hai bisogno di gestire correttamente caratteri insoliti (principalmente newline) nei nomi delle voci della directory, ti suggerisco di usare l' -bopzione ls per evitarli. ls -1bAstamperà il nome di ogni voce della directory sulla propria riga, sfuggirà a caratteri insoliti (quindi ogni voce della directory sarà vista come una), inclusi tutti i dotfile e -directory. Mettiti alla prova wc -lper una riga di comando completa ls -1bA | wc -lche riporterà il numero di file e directory nella directory corrente (ma ignora .e ..; questa è la differenza tra -ae -A), ma non scende in nessuna sottodirectory. Se non si desidera conteggiare alcun dotfile per il totale, è sufficiente omettere il -Aparametro ls.


Entrambi -ae -Aincludono anche file nascosti che ho capito che voglio evitare, quindi al massimo lo farei ls -b | wc -l, ma questo mi dà la risposta giusta. La riga copiata e incollata relativa a questo comando non è corretta? Se fosse corretto, non dovrei ottenere un output di 8 quando ci sono 6 file o cartelle in una directory?
Adam,

@Adam sì, probabilmente farà il trucco ("ls -b | wc -l"); puoi anche usare "-1" (trattino + numero uno) che forza un elenco in una singola colonna anziché tutto su una singola riga, ma ciò accade comunque quando si esegue il piping a un altro comando. Quindi (imho) lo lascerei come "ls -1b | wc -l"; e per "testare", eseguire "ls -1b" e contare il numero di righe, quindi eseguire "ls -1b | wc -l" e verificare i risultati. (Ecco come eseguire il debug / test delle pipe.)
michael

@Sardathrion, quella FAQ è abbastanza fuorviante. Le convenzioni del filesystem Unix non sono "strane"; dove sono comuni è l' altro sistema che li raccoglie. Ma ok. Quindi dice che il "comando file utilizza numeri magici per identificare ...", il che è sbagliato: utilizza anche molta euristica. Non molto affidabile nel mio libro.
vonbrand,

@vonbrand: abbastanza giusto, link eliminato. L'ho appena sfiorato e mi è sembrato perfetto. So di averne trovato uno buono ma che ora non ricordo dove fosse.
Sardathrion - Ripristina Monica il

1
Ti stai sbagliando: . e ... sono manufatti storici di UNIX negli anni '70 e derivano da un'epoca in cui non vi era ancora alcuna mkdir()chiamata di sistema. Non tutti i filesystem li hanno e non sono nemmeno necessari né richiesti da POSIX.
schily

6

Per rispondere alla domanda nell'argomento:

Quando una directory B viene creata in Unix, viene aggiunta come nuova voce a un'altra directory A (la sua directory principale) e in B vengono aggiunte due voci: una chiamata .come collegamento reale a se stessa e una chiamata ..come hard collegamento ad A.

Questi sono gli unici collegamenti concreti alle directory consentite (anche se alcune versioni precedenti di alcuni Unices consentivano anche collegamenti arbitrari).

ecco perché con la maggior parte dei file system ( btrfsessendo un'eccezione notevole), il numero linksdi una directory è un'indicazione di quante sottodirectory ha (tenendo conto delle loro ..voci).

Quando rinomini / sposti una directory, se si trova nella stessa directory (con un nome diverso), Aviene modificata solo la voce del nome in . B .e ..non è interessato. Ma se lo si sposta fare una directory diversa, quindi ..in Bcambierà. Ciò spiega perché è possibile rinominare una directory in cui non si dispone dell'accesso in scrittura (supponendo che si abbia accesso in scrittura alla directory principale) solo se non lo si sposta in un'altra directory (altrimenti la necessità di modificare la ..voce impedisce tu dal spostarlo).

Attenzione però: /a/b/../cpotrebbe non essere lo stesso di /a/cperché /a/bpotrebbe essere un collegamento simbolico ad un'altra directory.

Un'eccezione a ciò è quando quel percorso viene dato al cdcomando ad alcune shell. Questi cdtrattano .. logicamente ignorando le ..voci nelle directory. Un motivo per cui si vede spesso cd -Pnegli script scritti correttamente, per disabilitare quella funzione che altrimenti potrebbe causare confusione e incoerenze.

Per contare il numero di voci nella directory corrente escluso .e ..con bash, puoi fare:

shopt -s nullglob dotglob
set -- *
echo "$#"

Con zsh:

f=(*(ND))
echo $#f

portabile:

find . ! -name . -prune -print | grep -c /

Sono un po 'confuso; tutti e tre quelli che hai elencato ne aggiungono uno al conteggio effettivo. ad es. se ho 6 file o cartelle in una directory, ne generano 7, non 6. A me sembra che ls | wc -lsia l'unico ad escludere .e..
Adam

1
@Adam, lsnon elenca i file nascosti. Devi ls -Aottenere lo stesso di quelli. Se non si desidera contare i file nascosti, togliere dotglob(per bash) o D(per zsh) o aggiungere un ! -name '.*'precedente -printper find.
Stéphane Chazelas,

Sì, l'ho appena notato dopo aver effettivamente elencato i file. Sai allora perché ls | wc -lmi dà ancora la risposta giusta ed esclude i file nascosti, .& ..?
Adam,

1
Adam, nella tua directory, hai ., ..e un altro file il cui nome inizia con il .quale non è elencato da ls ma sarebbe da ls -A. Quindi ls | wc -lnon ti dà la risposta corretta perché non sta contando quel file nascosto.
Stéphane Chazelas,

1
Sì, .e ..sono file nascosti poiché iniziano con a .. C'è anche una leggenda che spiega che i dotfile sono nascosti per caso poiché un'implementazione precoce lsdoveva escludere solo .e .., ma c'era un bug che gli causava l'esclusione di qualsiasi file a partire da .. ls | wc -lnon funziona se i nomi dei file contengono caratteri di nuova riga.
Stéphane Chazelas,

1

Non sono un grande esperto di Linux, ma conosco Linux (era amministratore 16 anni fa, su Slackware :) un bel po 'di tempo

le directory ./ e ../ è semplice:. è la directory corrente, .. è la directory precedente (nella struttura di pwd -local directory command-

Se li conta, suppongo che aggiungano 2 al totale della lista, non vadano davvero ricorsivamente e contano la directory sotto quella corrente, e contano anche di nuovo la directory corrente (.) :))

Quindi in pratica penso che aggiunga il valore 2 per contare già (file) nella directory corrente.

Qualcuno mi corregga se sbaglio.

Sto solo postando per dare una mano e visto che nessuno ha risposto a questa domanda qui, potrebbero essere occupati. Ma sperimenta e vedi se hai 10 file e ottieni il conteggio di 12, allora è tutto.


Sì, Adrian ha ragione:. è la directory corrente e ... è la directory immediatamente sopra nella gerarchia.
schaiba,

.. non si riferisce sempre alla directory precedente nella struttura: in "/" .. si riferisce anche alla directory corrente.
Bonsi Scott,

perché potresti essere in / root del filesystem?
Adrian Tanase,

Se ne aggiunge due al numero di file in una directory, perché sto ottenendo la risposta corretta quando lo collaudo su Terminale su OSX? per esempio una directory con 6 file o cartelle produrrà 6, non 8 quando lo faròls | wc -1
Adam

Mi sono reso conto che è perché includono file nascosti (in particolare .ds_store), ma ancora non vedo come ls | wc -linclude .e ..quando ottengo la risposta giusta, al contrario della risposta giusta + 2.
Adam
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.