Один подход должен был бы использовать 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
так как это показывает то, что является каталогом и что является файлом.
$ 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
-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
способность считать байты вместо строк, wc -c
.
Здесь пригодится оператор перенаправления Айка. Вот несколько вариаций на эту тему.
cmd | sudo awk '{print >"/long/path/x." (NR==1 ? "load" : "conf")}'
cmd | sudo x=/long/path/x awk 'NR==1 {print >ENVIRON["x"]".load"}
NR==2 {print >ENVIRON["x"]".conf"}'
cmd | sudo awk 'FNR==1 && NR!=1 {exit} {print >ARGV[NR-1]}' - /long/path/x.{load,conf}
Первая - самая короткая и примерно такая же простая. Каждая строка выводится на имя файла, определяемое вычислением выражения после оператора >
. Для вычисления имени файла используется текущий номер строки NR
. Сопоставлением выражений является оператор конкатенация строк в awk.
Люди обычно делают это с помощью tee
:
cmd | sudo tee /long/path/x.{load,conf}
tee
записывает копии своих входных данных во все свои именованные выходные файлы - и точно так же перенаправление происходит перед exec
то же самое делает генерация аргумента при раскрытии фигурных скобок. Таким образом, приведенное выше должно работать нормально и записывать как результирующие имена файлов одновременно, так и стандартные.
Если вы предпочитаете не видеть, что tee
пишет на вашем терминале при копировании данных, вы можете перенаправить стандартный вывод в / dev / null
- sudo
не будет мешать этому перенаправлению.
Вы должны отметить, что - как написано - tee
будет обрезать выходные файлы перед записью в них. Если вы хотите добавить вместо этого, вы можете просто добавить переключатель -a
ppend, и tee
скопирует входные данные в конец всех именованных выходных файлов.
По общему признанию, записать каждую строку в отдельные места немного сложнее. Но sed
предлагает команду обряда w
. Объедините его с его аргументом -e
xpression, и вы можете написать весь скрипт sed
с раскрытием фигурных скобок:
cmd | sudo sed -e'$x;/./w '/long/path/x.{load,conf}$'\n1x'
... w
будет записывать первую строку в первый файл аргументов и во вторую строку во вторую. Изменения e x
просто балансируют скрипт между первой и второй строками - чтобы предотвратить запись обеих строк в оба файла для каждой строки sed
.
Я проверил это так:
printf %s\\n 1 2 |
sed -e'$x;/./w '/tmp/{1,2}$'\n$!x'
... а потом запустил ...
head /tmp/[12]
... который напечатал ...
==> /tmp/1 <==
1
==> /tmp/2 <==
2
Я не уверен, хотите ли вы, чтобы решение скриптовало все это (от команды cmd
до . загрузить настройки файлов
и .conf
, но в соответствии с настройками этого файла вы все равно можете сделать это с помощью sudo, но вам действительно нужно, чтобы перенаправление было частью команды sudoed :
$ sudo sh -c "echo 'foo' > /long/path/x.load"
$ sudo sh -c "echo 'bar' > /long/path/x.conf"
Здесь sudo
получит более высокие привилегии, затем запустит оболочку sh
, которая, в свою очередь, интерпретирует данную команду, и только в этот момент произойдет перенаправление, избегая проблем с привилегиями. .
Если по какой-либо причине вам понадобится сценарий, в зависимости от ваших конкретных потребностей это может выглядеть примерно так:
cmd | {
read line
sudo sh -c "echo '$line' > /long/path/x.load"
read line
sudo sh -c "echo '$line' > /long/path/x.conf"
}