Як я можу використовувати счетчик слів ( wc) та трубопроводів, щоб підрахувати, скільки файлів чи каталогів є в /usr/binкаталозі?
Як я можу використовувати счетчик слів ( wc) та трубопроводів, щоб підрахувати, скільки файлів чи каталогів є в /usr/binкаталозі?
Відповіді:
Одним із підходів було б скористатися для того, lsщоб надати нам список файлів, але ми хочемо, щоб у цьому списку було відображено лише 1 файл чи каталог у рядку. -1Вимикач робитиме це для нас.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Створіть наведені вище зразки даних у порожньому каталозі.
$ mkdir dir{1..3}
$ touch file{A..C}
Перевір це:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Тепер для підрахунку ви можете використовувати wc -lдля підрахунку кількості рядків, які відповідають файлу або каталогу у ls -1висновку.
$ ls -1 | wc -l
6
(проте зауважте, що він не містить прихованих файлів)
Для підрахунку файлів чи каталогів потрібно трохи змінити тактику. У цьому випадку я б використовував, ls -lоскільки він показує, що таке каталог та що файл aa.
$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Тоді ми можемо використовувати grepдля фільтрації каталогів чи не-каталогів так:
# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Тепер просто використовуйте wc -lще раз, щоб порахувати вище:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Хоча, ви можете уникнути в wcцілому, і використання grep«s -cваріанти:
$ ls -l | grep -c '^d'
(знову ж таки, приховані файли не включаються. Зауважте, що каталоги та регулярні файли - це два типи. Є ще багато таких як названі труби, символічні посилання, пристрої, розетки ...).
Якщо вам потрібно знайти файли та каталоги рекурсивно, /usr/binтоді ви, ймовірно, захочете повністю змінити тактику і скористатися іншим інструментом, який називається find.
$ find /usr/bin | wc -l
4632
(хоча вище /usr/binвходить до складу рахунку)
Ті ж методи, які я використовував вище, можна використовувати, lsщоб зробити щось подібне, але, lsяк правило, не є гарним інструментом для аналізу результатів. findз іншого боку, для цього був побудований і пропонує комутатори для пошуку або файлів, або каталогів.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(зауважте, що цього разу, findвключаючи приховані файли (крім .і ..)).
Я ніколи не з'ясовував, чому символ нового рядка є юридичним символом, який слід використовувати при створенні імен файлів або імен каталогів. Тож методи, про які йшлося вище, використовуючи wcі lsне суперечать цим, тому використовуйте їх, маючи на увазі.
Створіть каталог та ім’я файлу з новими рядками.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls показує їх правильно:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Але wcвважає каталоги та файли, що містять нові рядки, як 2 елементи, а не один.
$ ls -1 | wc -l
10
Один із способів подолати це, якщо використовується реалізація GNU, - findце використовувати findздатність друкувати щось інше замість кожного знайденого файлу, а потім замість них рахувати.
$ find . -printf . | wc -c
9
Тут ми знаходимо все в поточному каталозі ( за винятком ..), і друк точка ( .) для кожного, а потім підрахунок точок , використовуючи wcздатність «s для підрахунку байт замість рядків, wc -c.
/usr/binбудуть добре відформатовані (а також не містять пробілів, з технічної точки зору, ви могли б навіть просто echo * | wc -w), варто зазначити, що всі вони будуть розбиті на назви файлів, що містять нові рядки.
ls -lчи ls -1/ ми будемо рахувати рядки, а не слова! findМоже зламатися, але знову ж , ми розраховуємо рядки не слово.
touch $'foo\nbar'у порожньому каталозі, за яким слідує одна з ваших команд (скажімо ls -1 | wc -l), буде повідомлено два файли, а не один - тому що цей файл - це два рядки, наскільки wcце стосується. Якщо тільки не lsзамінює нові рядки якимось іншим символом (я не думаю, що це робить, але я знову не в змозі перевірити зараз).
wc -cпроблема під час підрахунку періодів?
Якщо ви хочете отримати кількість даних про файл кожного типу рекурсивно під деяким режимом, за допомогою GNU find, ви можете зробити:
find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
У /usr/binмоїй системі, що дає:
3727 regular files
710 symbolic links
Увімкнено /dev:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Для символьних посилань, якщо ви краще вважаєте їх типом файлу, на який вони вказують, а не symbolic links, ви можете змінити його на:
find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/N/broken symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Що тепер дає за моє /usr/bin:
1 directories
4434 regular files
2 broken symbolic links
(ламане символьне посилання - це посилання на файл, для якого findне можна визначити тип, тому що файл не існує, або знаходиться в каталозі, до якого ви не маєте доступу, або є петля в роздільній здатності файлу. . У моєму випадку, ті 2, де посилаються на файли, яких тепер немає).
Ніхто з них не рахує .і ... Якщо ви хотіли, щоб вони були включені (чому б вам це зробити?), Немає іншого способу, findніж припустити, що вони є для кожного каталогу та систематично рахувати їх:
find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
-type d -printf 'd\nd\n' \) | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Що потім дає на моє /usr/bin:
2 directories
3727 regular files
710 symbolic links
Якщо у вас немає доступу до GNU find, ви можете переписати перший як:
find /some/dir/. ! -name . \( \
-type f -exec printf '%.0sregular files\n' {} + -o \
-type d -exec printf '%.0sdirectories\n' {} + -o \
-type l -exec printf '%.0ssymbolic links\n' {} + -o \
-type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
-type b -exec printf '%.0sblock devices\n' {} + -o \
-type c -exec printf '%.0scharacter devices\n' {} + -o \
-type p -exec printf '%.0sFIFOs\n' {} + -o \
-exec printf '%.0sothers\n' {} + \) | sort | uniq -c
Тепер, строго кажучи, ми рахували не файли, а записи каталогів . Каталог, як /usr/binправило, має кілька записів, які вказують на один і той же файл. Наприклад, тут я маю:
$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview
Це 3 записи каталогів (імена файлів ака ж жорсткі посилання) на той самий файл (той, який має inode 672252. Для підрахунку файлів замість записів каталогів та з GNU findта GNU uniq(ігнорування .та ..файли, які так чи інакше є жорсткими посиланнями на інші каталоги):
find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
sort -u |
cut -f1 |
uniq -c |
sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/d/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
По моєму /usr/bin, це дає:
3711 regular files
710 symbolic links
Ви ще не говорили, чи хочете, щоб весь файл під / usr / bin був рекурсивно або просто під першим рівнем. Крім того, як ви збираєтеся отримати слова, які ви рахуєте? Звичайний спосіб з'ясувати це запустити пошук у туалет. Ось так: знайти / usr / bin | wc -l Find перерахує все там, каталоги та файли. Wc -l буде рахувати всі рядки у знаходженні результатів. Це завдання для класу? Це нормально, якщо це так, але мені було цікаво, навіщо вам потрібна ця інформація, щоб я міг більш ретельно адаптувати відповідь. Будь ласка, дайте мені знати, якщо вам потрібно більше. Коста
Баш, без зовнішніх інструментів.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
Баш, без зовнішніх інструментів та рекурсії.
shopt -s globstar; shopt -s dotglob
for dir in **/*/; do
unset d f
for files in "$dir"*; do
[[ -f $files ]] && ((++f))
[[ -d $files ]] && ((++d))
done;
printf '%s\n' "$dir - files: ${f:-0} - directories: ${d:-0}"
done
.ані ..записи. Ви можете роз’єднати файл проти звичайного файлу.