подстановка процесса для открытия списка файлов с приложением

Я хочу использовать подстановку процессов, чтобы направлять список файлов (созданных, например, ls или find ) в конкретное приложение для открытия / просмотра. Хотя такой список для xargs подходит для скрипта или двоичного xargs , это действие терпит неудачу, если объект xargs является псевдонимом оболочки, как указано в других вопросах на этом сайте . [Особое приложение, которое я имею в виду, есть, но я сомневаюсь, что это важно для вопроса.]

Учитывая это ограничение xargs vis-a-vis bash aliases, я вместо этого xargs использовать замену процесса в форме [script/binary/alias] <(find . -iname '*') . Эта конструкция дает желаемый эффект, если список файлов направлен на определенные команды оболочки, такие как cat (или less , если перенаправление ввода, < , добавлено в оператор замещения процесса); однако, это заметно, если вход (список путей к файлам) вместо этого направляется в приложение (например, feh , gimp ) для открытия / просмотра. Ошибка, сопровождающая этот сбой, в частном случае, когда feh является получателем оператора подстановки процесса, является « feh: No loadable images specified. ». feh: No loadable images specified. оператора перенаправления ввода в оператор замещения процесса не устраняет проблему (в отличие от случая для других команд, например, less ).

Таким образом, мой вопрос касается того, может ли замена процесса использоваться для заявленной цели (т. Е. Открытия списка файлов), и если да, то каким может быть соответствующий синтаксис. В случае, если другое решение (не связанное с заменой процесса) более уместно, сообщите об этом соответствующим образом. Обратите внимание на специфическое требование совместимости с ~/.bash_aliases bash (указано в ~/.bash_aliases или аналогичном файле конфигурации).

2 Solutions collect form web for “подстановка процесса для открытия списка файлов с приложением”

Если команда принимает несколько файлов в качестве аргументов (а не как содержимое, просматриваемое в трубе), должна работать простая подстановка команд:

 [script/binary/alias] $(find .) 

В качестве альтернативы, если команда принимает только один файл за раз, цикл for должен делать трюк:

 for file in $(find .); do [script/binary/alias] "$file"; done 

В обоих случаях имена файлов, содержащие пробелы, табуляции, символы новой строки, подстановочные знаки, вызовут проблемы; a while / read loop обрабатывает это:

 find . | while IFS= read -r file; do [script/binary/alias] "$file"; done 

Имена файлов, содержащие новые строки, по-прежнему будут создавать проблемы; вывод 0 с разделителями будет адресован тем (здесь предполагается bash , zsh , ksh ):

 find . -print0 | while IFS= read -rd '' file; do [script/binary/alias] "$file"; done 

Во всех этих примерах find . -type f find . -type f может быть более уместным, если вы хотите обрабатывать обычные файлы.

Если вы хотите расширить псевдонимы после xargs , вы можете сделать следующее:

 alias xargs='xargs ' 

Однако обратите внимание, что только первое слово после xargs подвержено расширению псевдонимов и может иметь неожиданные эффекты, если у вас есть псевдонимы для стандартных команд.

 $ alias xargs='xargs ' a='echo test' $ set -x $ echo x | xargs a + echo x + xargs echo test test x $ echo x | xargs -ra + echo x + xargs -ra xargs: a: No such file or directory 

Возможно, вы захотите назвать свой псевдоним чем-то другим и использовать более разумное поведение по умолчанию для xargs . Например, с GNU xargs :

 alias axargs='xargs -r -d "\n" ' 

Теперь подстановка процесса расширяется до одного аргумента: имя файла, который для <(...) содержит вывод команды (как живой поток).

С выходом find это полезно только для команд, которые принимают в качестве аргумента имя файла, которое, как ожидается, будет содержать список файлов, разделенных новой строкой.

feh – один из них:

 feh -f <(find . -mtime -1 -type f -name '*.jpg') 

Это работает только в том случае, если имена файлов не содержат символов новой строки.

Реализация xargs в xargs имеет параметр -a чтобы взять список аргументов из файла и в сочетании с параметром -0 и -print0 (или -exec printf '%s\0' {} + ), чтобы find позволяет передать список имен файлов надежно:

 xargs -r0a <(find ... -print0) feh.... 

Тем не менее это не помогает вашей проблеме с псевдонимами.

Теперь, если вы хотите передать вывод команды в качестве аргумента (ов) другой команде, вы должны использовать замену команд, а не замену процесса . Остерегайтесь нескольких оговорок.

 cmdA "$(cmdB)" 

передает вывод cmdB , без символов новой строки в качестве одного аргумента в cmdA . Например, если у вас есть три обычных файла (здесь с необычными, хотя и вполне допустимыми именами): * * /etc/passwd .jpg , foo.txt и <nl><nl> (где <nl> означает символ новой строки), выход find . -type f cmdB find . -type f ( cmdB ) будет ./* * /etc/passwd .jpg<nl>./foo.txt<nl>./<nl><nl><nl> , поэтому cmdA получит один аргумент ./* * /etc/passwd .jpg<nl>./foo.txt<nl>./ .

Это, вероятно, не то, что вы хотите. Вы хотите, чтобы cmdA получал каждое имя файла в виде отдельных аргументов: ./* * /etc/passwd , ./foo.txt и ./<nl><nl> .

Итак, в принципе, вам нужно разделить результат find на отдельные имена файлов. У оболочек POSIX есть оператор для этого, оператор split + glob, который неявно вызывается, когда вы оставляете подстановку команд (или расширение параметра или арифметическое расширение) некорректными.

 cmdA $(cmdB) 

будет разделять вывод cmdB (без конечных символов новой строки) на символы $IFS (по умолчанию пробел, табуляция и cmdB ), а затем каждое слово будет подвергнуто глобулизации.

В нашем примере выше, это не то, что мы хотим. Это разделило бы ./* * /etc/passwd .jpg на ./* , * , /etc/passwd и .jpg и те ./* и * были бы заглочены в список файлов в текущем каталоге.

Мы хотим разделить на символы новой строки, а не делать глобирование. Это делается с помощью:

 IFS=' ' # newline only set -f cmdA $(cmdB) 

Это все еще не работает для имен файлов, содержащих символы новой строки. Результат find обычно не обрабатывается после обработки, если вы не используете -print0 или можете гарантировать, что имена файлов с символами новой строки не будут.

Теперь только zsh разрешает разбиение на символы \0 :

 cmdA ${(0)"$(cmdB)"} 

разделил бы "$(cmdB)" на последовательности символов NUL. Или:

 IFS=$'\0' # no need for set -f in zsh cmdA $(cmdB) 

Еще одна проблема с подстановками подстановки команд заключается в том, что если cmdB терпит неудачу и / или ничего не выводит, cmdA все равно будет выполняться (без аргумента). Этого можно избежать с помощью этого синтаксиса (все еще с zsh ):

 cmdA ${$(find...):?no file} 

Но если вы используете zsh , вам вообще не нужно сбрасывать все эти проблемы, так как zsh поддерживает большинство функций find внутри. Например, вы должны использовать:

 myalias ./**/*.jpg(.m-1) 

Чтобы отобразить файлы jpg последние изменения за последние 24 часа.

  • Пакетная копия в несколько каталогов
  • вывод искажается при параллельном запуске «xargs ls»
  • Расширение оболочки оболочки Ubuntu - путаница с командой sox
  • команда solaris + xargs для солярия
  • Когда вы должны использовать подоболочки vs `xargs`?
  • Как я могу найти файлы, а затем использовать xargs для их перемещения?
  • Удаление файлов с пробелами в именах
  • Как выполнить выходную строку без замены команды bash?
  • Найти -exec + vs find | xargs. Какой из них выбрать?
  • find + xargs: строка аргумента слишком длинная
  • Комбинация ls, xargs и zcat приводит к дублированию суффиксов имени файла?
  • Linux и Unix - лучшая ОС в мире.