Создайте 2 файла с похожими именами с содержимым из 2-строчного вывода команды

Один подход должен был бы использовать 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.

Ссылки

3
06.06.2015, 23:31
3 ответа

Здесь пригодится оператор перенаправления Айка. Вот несколько вариаций на эту тему.

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.

2
27.01.2020, 21:22

Люди обычно делают это с помощью 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
1
27.01.2020, 21:22

Я не уверен, хотите ли вы, чтобы решение скриптовало все это (от команды 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"
}
0
27.01.2020, 21:22

Теги

Похожие вопросы