Трубопроводные команды после харга по трубопроводу

38

HP-UX ***** B.11.23 U ia64 **** безлимитная лицензия

find . -type d -name *log* | xargs ls -la

дает мне имена каталогов (те, которые содержатся logв имени каталога), за которыми следуют все файлы в этом каталоге.

Каталоги  /var/opt/SID/application_a/log/,  /var/opt/SID/application_b/log/,  /var/opt/SID/application_c/log/и так далее содержат файлы журналов.

Я хочу, чтобы команда указала только два последних файла журнала ls, которые я обычно использую ls -latr | tail -2.

На выходе должно быть что-то вроде этого ..

/var/opt/SID/application_a/log/
-rw-rw-rw-   1 user1    user1      59698 Jun 11  2013 log1
-rw-rw-rw-   1 user1    user1      59698 Jun 10  2013 log2
/var/opt/SID/application_b/log/
-rw-rw-rw-   1 user1    user1      59698 Jun 11  2013 log1
-rw-rw-rw-   1 user1    user1      59698 Jun 10  2013 log2
/var/opt/SID/application_c/log/
-rw-rw-rw-   1 user1    user1      59698 Jun 11  2013 log1
-rw-rw-rw-   1 user1    user1      59698 Jun 10  2013 log2

find . -type d -name *log* | xargs ls -la | tail -2не дает мне вышеуказанный результат. То, что я получаю, это список последних двух find . -type d -name *log* | xargs ls -laкомандных файлов .

Так я могу передать команды после передачи по каналу xargs? Как еще я могу запросить, чтобы получить результирующий список файлов в вышеуказанном формате?

find . -type d -name *log* | xargs sh -c "ls -ltr | tail -10"

дает мне список из десяти имен каталогов внутри текущего каталога, который, как оказалось, /var/opt/SIDи это тоже не то, что я хочу.

anotherperson1
источник
2
Вы должны указать в *log*противном случае оболочка расширит его.
Энтон
Имейте в sh -cвиду, что ожидает имя команды (параметр 0) в качестве второго аргумента, поэтому вы всегда должны это делать find . -type d -name *log* | xargs sh -c "ls -ltr | tail -10" lstail(обратите внимание lstailна конец, который будет служить $0для созданной оболочки). В противном случае первый из ваших результатов заполнит эту роль и останется неиспользованным.
Джонас

Ответы:

58

Вы почти там. В вашей последней команде вы можете использовать, -Iчтобы сделать lsправильно

-I replace-str

    Заменить вхождения replace-str в исходных аргументах именами, считанными из стандартного ввода. Кроме того, пробелы без кавычек не заканчивают элементы ввода; вместо этого разделителем является символ перевода строки. Подразумевается -xи -L 1.

Итак, с

find . -type d -name "*log*" | xargs -I {} sh -c "echo {}; ls -la {} | tail -2"

Вы echoнайдете каталог find, а затем сделайте ls | tailэто.

fredtantini
источник
находить . -типа d -name " log " | xargs -I {} sh -c "echo {}; ls -ltr {} | grep -E \" file_in | file_out \ "| tail -5" Я использовал этот.
anotherperson1
3
Я делаю сxargs -n 1 sh -c 'echo $0'
Ginhing
1
в macOS замена не работала в указанной команде, поэтому echo $0была полезна (и более понятна)
mpuncel
1
Для того, чтобы заставить его работать с именами файлов с пробелами, использования -print0, xargs -0и бежать {}в двойные кавычки внутри в shкоманде:find . -type d -name "*log*" -print0 | xargs -0 -I {} sh -c "echo \"{}\";ls -la \"{}\" | tail -2"
Бенедикту Köppel
Я использую "xargs -n 1 sh -c" echo \ $ 0 | $ func "` если мне нужно использовать переменную $ func
бог
5

GNU Parallel упрощает такие задачи:

find . -type d -name "*log*" | parallel --tag "ls -la {} | tail -2"

Если вы не хотите делать полную установку GNU Parallel, вы можете выполнить минимальную установку: http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Оле Танге
источник
2

Просто в дополнение к fredtantini и в качестве общего пояснения (поскольку документы немного сбивают с толку):

Команда xargs -I {}возьмет символы '{}' из стандартного ввода и заменит их на все, что приходит из канала. Это означает, что вы могли бы заменить {}любую комбинацию символов (возможно, для лучшего соответствия вашему предпочтению программирования). Например : xargs -I % sh -c "echo %". Если вы всегда используете его, xargs -I {}вы можете заменить его xargs -iна условное обозначение.

Команда sh -cскажет вашей bash / shell читать следующую команду из строки, а не из стандартного ввода. Так что написание sh -c "echo something"эквивалентно echo something.

xargs -I {} sh -c "echo {}"Будет читать ввод созданных с помощью sh -cкоторой является echo {}. Так как вы сказали заменить {}его аргументами, полученными из канала, вот что произойдет.

Вы можете легко проверить это, даже не прибегая к трубопроводу, просто введите указанную выше команду в терминале. Все, что вы напишете дальше, будет выведено на терминал (Ctrl-D для выхода).

В ls -la {}команде то же самое происходит снова. {}Заменяется содержимым команды предварительной трубы.

Borisu
источник