Как выполнить команду на каждом входе, учитывая список входных данных

У меня есть папка, и я хочу записать в каждую папку и запустить команду. Я чувствую, что это должно быть примерно так:

(Ниже приведен надуманный и упрощенный пример того, что я хочу сделать).

ls | xargs echo 'Looking at {}' && cd {} && /bin/do_stuff 

Но это не работает. Как мне это сделать?

2 Solutions collect form web for “Как выполнить команду на каждом входе, учитывая список входных данных”

Это не работает, потому что xargs выполняет свою команду напрямую. Он не принимает строку кода оболочки и передает команду на выполнение оболочки. Фактически, все эти && s интерпретируются оболочкой до xargs даже ls и xargs . Кроме того, {} представляет собой конструкцию, которая find понимает, а не xargs .

(Вы можете использовать -I с xargs чтобы имитировать эту функцию find , если хотите.)

Самый простой способ сделать это с помощью xargs – поместить вашу команду в сценарий оболочки:

 #!/bin/sh echo "Looking at $1" cd $1 /bin/do_stuff 

(Я эффективно заменил ваш && ; поскольку он выглядит так, как echo и cd не могут потерпеть неудачу, если вы запустите это в каталоге, который содержит только другие подкаталоги. Если вам нужно «и» поведение, требуемое исправление для скрипта очевидно.)

Затем запустите этот сценарий оболочки через xargs . Если вы назвали его dostuff.sh :

 $ ls | xargs ./dostuff.sh 

dostuff.sh должен быть отмечен как исполняемый файл, например, с chmod +x dostuff.sh .

Вероятно, есть способ написать все это в одной строке с sh -c , но если вы не можете вспомнить волшебство, чтобы сделать что-то такое, это в основном просто любопытство, не так ли?

xargs – правильный инструмент, но его сложно использовать.

xargs не запускает оболочку, если вы не сообщите об этом. Он выполняет команду, указанную в первом аргументе без параметра, и передает ему другие аргументы в своей командной строке, за которой следуют аргументы, считанные со стандартного ввода. Например

 echo hello world | xargs echo 'Looking at' 

запускает echo 'Looking at' hello world . Чтобы запустить команду один раз для каждой строки ввода, используйте xargs -L1 :

 (echo hello; echo world) | xargs -L1 echo 'Looking at' 

Поскольку вы хотите, чтобы xargs запускала команду оболочки, вам нужно заставить ее явно вызывать оболочку.

 (echo hello; echo world) | xargs sh -c 'echo "Looking at $0" && cd "$0" && /bin/do_stuff' 

(Или tcsh -c если вы действительно этого хотите, но приходите один, это 21-й век.)

Вы можете использовать -I {} для интерполяции {} внутри этой команды, но будьте осторожны, что это работает только в том случае, если вход не содержит специальных символов оболочки. Передача ввода в качестве аргумента команды ( $0 выше) имеет то преимущество, что не делает никаких предположений на входе (за xargs -L разделения строк и не содержит конечных пробелов в соответствии с синтаксисом xargs -L ).

В оболочке Bourne / POSIX альтернативный подход, который использует больше строк, но намного более ясный, заключается в использовании цикла вокруг встроенной оболочки read :

 { echo hello; echo world; } | while IFS= read -r line; do echo "Looking at $line" (cd "$line" && /bin/do_stuff) done 

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

  • TCSH побитовый | оператор
  • Как получить список ярлыков tcsh?
  • tcsh: сбой символа i-search-back
  • Tcsh: поиск истории с помощью Ctrl-P и Ctrl-N
  • название динамического окна из ввода команды (TCSH)
  • Как правильно использовать $ _ внутри скрипта tcsh, полученного из другого tcsh-скрипта?
  • Как временно обходить псевдоним в tcsh?
  • Когда переменные окружения устанавливаются в tcsh?
  • Как заставить tcsh не вставлять пробелы в команду, которая охватывает несколько строк
  • Подавлять сообщения о запуске на stdout?
  • Различные оболочки для интерактивной и неинтерактивной работы
  • Linux и Unix - лучшая ОС в мире.