Що таке каталоги ./ та ../?


20

Просте запитання, але я не впевнений, куди шукати, а Google не відповідає на періоди та косої риски.

Я просто намагаюся підрахувати # файлів і каталогів в поточному каталозі (не включаючи вкладені папки / файли) і намагається диференціювати ls -1 | wc -lі , ls | wc -lтак як вони здаються однаковими. Сайт, на який я переглядав, сказав: "Майте на увазі, що це також враховує каталоги ./ і ../". щодо того, з ким ls -1, і я не впевнений, чи це означає, що він включає до себе каталоги або щось таке (чого я не хочу), але, здається, це не робилося на тестуванні.

Чи може хтось підтвердити, який із них буде найбільш адекватним для підрахунку # файлів та каталогів лише у поточному каталозі (не підпорядкованому) та що вони означають під каталогами ./ та ../?


"Майте на увазі, що це також підрахунок каталогів ./ і ../" є помилковим (якщо це не помилки для "." І "..".
vonbrand

Відповіді:


15

Кожен каталог у системі Unix (і, мабуть, і будь-яка інша система) містить щонайменше дві записи каталогів. Це .(поточний каталог) та ..(батьківський каталог). Що стосується кореневого каталогу, вони вказують на те саме місце, але в будь-якому іншому каталозі вони відрізняються. Ви можете побачити це для себе , використовуючи stat, pwdі cdкоманди (на 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
/
$

Зверніть увагу , що binі sbinкожен з них має два посилання на нього. Один - це запис каталогу в кореневому каталозі, а другий - .запис всередині цього каталогу.

Використання " lspipe" до wc -l- простий трюк для підрахунку кількості рядків у висновку ls. Припущення полягає в тому, що кожен файл або каталог буде займати рівно один рядок у висновку. GNU ls, коли вихід є нетермінальним, зробить це автоматично; іншим може знадобитися -1опція, щоб чітко ввімкнути поведінку. wc -lпросто підраховує та виводить кількість рядків ( -l) у своєму введенні.

Проблема такого підходу полягає в тому, що в Linux та файлових системах, які традиційно використовуються в Linux, імена файлів та каталогів (вони в цьому плані дійсно є одними і тими ж) можуть містити символи нового рядка . За наявності цих методів розпадається будь-який метод - ці записи будуть рахуватися як два або більше записів, якщо насправді вони є одним.

Поки ви використовуєте GNU ls, не має записів каталогів з іменами, що містять символи нового рядка, і не мають непарних псевдонімів ls(наприклад, ls -a), обидва будуть виводити кількість файлів і каталогів у поточному (або вказаному) каталозі. Для більшості людей це досить добре, але в загальному випадку це не вірно .

Якщо вам потрібно правильно обробляти незвичні символи (в першу чергу нові рядки) в іменах запису каталогу, я пропоную скористатися -bпараметром ls, щоб уникнути їх. ls -1bAбуде надрукувати кожну назву вхідного каталогу у власному рядку, уникаючи незвичних символів (тому кожен запис у каталозі буде розглянуто як один), включаючи будь-які точкові файли та -директорії. Увійдіть wc -lу повний командний рядок, ls -1bA | wc -lякий повідомить про кількість файлів і каталогів у поточному каталозі (але ігноруйте .і ..; це різниця між -aі -A), але не спускається в жодні підкаталоги. Якщо ви не хочете, щоб якісь точкові файли зараховувались до загальної суми, просто опустіть -Aпараметр до ls.


Обидва , -aі -Aвключають в себе приховані файли і які я зрозумів , що я хочу , щоб уникнути, так саме я хотів би зробити ls -b | wc -l, але це дає мені правильну відповідь. Чи неправильний рядок, який я копіюю та вставляю щодо цієї команди, невірний? Якщо це було правильно, чи не повинен я отримувати вихід 8, коли в каталозі є 6 файлів або папок?
Адам

@Adam так, це, ймовірно, зробить трюк ("ls -b | wc -l"); ви також можете використовувати "-1" (тире + номер один), який примушує список у одному стовпчику замість усіх на одному рядку, але це все одно відбувається під час передачі в іншу команду. Тож (імхо) я би залишив це як "ls -1b | wc -l"; і для "тестування" запустіть "ls -1b" і порахуйте кількість рядків, потім запустіть "ls -1b | wc -l" і перевірте результати. (Ось як налагоджувати / пробувати труби.)
michael

@Sardathrion, що FAQ досить вводить в оману. Конвенції файлової системи Unix не "дивні"; там, де вони поширені, це інша система, яка їх збирає. Але гаразд. Потім йдеться про те, що "команда файлів використовує магічні числа для ідентифікації ...", що неправильно: воно також використовує багато евристики. Не дуже надійний у моїй книзі.
фонбранд

@vonbrand: досить справедливо, посилання видалено. Я просто скуйовдився, і це здалося прекрасним. Я знаю, що знайшов добре, але тепер не можу згадати, де це було.
Сардатріон

1
Ви помиляєтесь:. і .. є історичними артефактами UNIX в 1970-х роках і є результатом того часу, коли ще не було mkdir()системного дзвінка. Не всі файлові системи мають їх, і вони навіть не потрібні і не вимагаються POSIX.
шилі

6

Щоб відповісти на запитання з теми:

Коли в Unix створений каталог B, він додається як новий запис до іншого каталогу A (його батьківського каталогу), а в B додаються два записи: один викликається .як жорстке посилання до себе, а інший - ..як жорсткий посилання на А.

Це єдині жорсткі посилання на каталоги, дозволені (хоча деякі старі версії деяких Unices також дозволяли довільні посилання).

ось чому в більшості файлових систем ( btrfsщо є помітним винятком) кількість linksкаталогів є вказівкою на те, скільки у них є підкаталогів (враховуючи їх ..записи).

Коли ви перейменовуєте / переміщуєте каталог, якщо він перебуває у тому самому каталозі (під іншим іменем), Aзмінюється лише запис у імені . Б .і ..не зачіпається. Але якщо ви перемістите його в інший каталог, то ..в Bбуде змінено. Це пояснює, чому ви можете перейменовувати каталог, до якого у вас немає доступу для запису (якщо припустити, що у вас є доступ для запису до батьківського каталогу) лише до тих пір, поки ви не перемістите його в інший каталог (інакше необхідність змінити ..запис перешкоджає ви від переміщення).

Але /a/b/../cбудьте обережні: можливо, це не те саме, що /a/cтому, що це /a/bможе бути символічним посиланням на якийсь інший каталог.

Винятком є ​​те, коли цей шлях дається cdкоманді до деяких оболонок. Вони cdтрактують .. логічно ігноруючи ..записи в каталогах. Причина, чому ви часто бачите cd -Pв правильно написаних сценаріях, щоб відключити функцію, яка в іншому випадку може викликати плутанину та невідповідності.

Щоб підрахувати кількість записів у поточному каталозі, виключаючи .та ..з bash, ви можете зробити:

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

З zsh:

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

Портативно:

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

Я трохи розгублений; всі три з перелічених вами додають один до фактичної кількості. наприклад, якщо у мене в каталозі є 6 файлів або папок, вони виводять 7, а не 6. Мені здається, що ls | wc -lце єдине, за винятком .і..
Adam

1
@Adam, lsне перераховує приховані файли. Вам потрібно ls -Aотримати те саме, що і ті. Якщо ви не хочете рахувати приховані файли, зніміть dotglob(для bash) або D(для zsh) або додайте ! -name '.*'до -printдля find.
Стефан Шазелас

Так, я щойно помітив це після фактичного переліку файлів. Чи знаєте ви тоді, чому ls | wc -lвсе-таки дає мені правильну відповідь і виключає приховані файли ? .& ..?
Адам

1
Адам, в каталозі, у вас є ., ..і інший файл, ім'я якого починається з .якої не вказана Л.С. , але буде по ls -A. Тож ls | wc -lне дає точної відповіді, оскільки він не рахує цей прихований файл.
Стефан Шазелас

1
Так, .і ..є прихованими файлами, оскільки вони починаються з .. Існує навіть легенда, яка пояснює, що dotfiles приховані випадково, оскільки рання реалізація lsповинна була виключати лише .і .., але виникла помилка, яка викликала виключення будь-якого файлу, починаючи з .. ls | wc -lне працює, якщо назви файлів містять символи нового рядка.
Стефан Шазелас

1

Я не чудовий експерт Linux, але знаю Linux (коли він був адміністратором 16 років тому, на Slackware :) гарний старий час

каталоги ./ і ../ просто:. поточна директорія, .. - це попередній каталог (у дереві pwd - команда локального каталогу-

Якщо вона їх підраховує, я вважаю, що вони додають 2 до загальної кількості лістингу, а не рекурсивно і підраховують каталог нижче поточного, а також знову підраховують поточний каталог (.) :))

Отже, я думаю, що він додає значення 2 до вже підрахунку (файлів) у поточному каталозі.

Хто-небудь виправить мене, якщо я помиляюся.

Я просто дописую, щоб допомогти, і побачив, що ніхто не відповів на це запитання, вони можуть бути зайняті. Але просто експериментуйте і подивіться, чи є у вас 10 файлів і налічуєте 12, то це все.


Так, Адріан правильний:. є поточним dir і .. - це каталог безпосередньо в ієрархії.
schaiba

.. не завжди посилається на попередній каталог у дереві: в "/" .. також посилається на поточний каталог.
Бонсі Скотт

тому що ви можете бути в / root файлової системи?
Адріан Танасе

Якщо він додає два до # файлів у каталозі, чому я отримую правильну відповідь під час тестування його в терміналі на OSX? наприклад, каталог із 6 файлами чи папками видасть 6, а не 8, коли я це робитиls | wc -1
Адам,

Я зрозумів, що це тому, що вони включають приховані файли (а саме .ds_store), але я все ще не бачу, як це ls | wc -lстосується .і ..коли я отримаю правильну відповідь, на відміну від правильної відповіді + 2.
Адам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.