Как выполнить несколько команд после xargs -0?
find . -name "filename including space" -print0 | xargs -0 ls -aldF > log.txt
find . -name "filename including space" -print0 | xargs -0 rm -rdf
Можно ли объединить эти две команды в одну так, чтобы вместо 2?
было выполнено только 1 find?
Я знаю, что для xargs -I могут быть способы сделать это, что может привести к ошибкам при продолжении имен файлов, включая пробелы. Любые рекомендации очень ценятся.
Ответы
Ответ 1
Если вам просто нужно избегать find
несколько раз, вы можете сделать tee
сразу после find
, сохранив вывод find
в файл, а затем выполнив строки как:
find . -name "filename including space" -print0 | tee my_teed_file | xargs -0 ls -aldF > log.txt
cat my_teed_file | xargs -0 rm -rdf
Другой способ выполнить эту же задачу (если это действительно так, чего вы хотите достичь) - сохранить вывод find
в переменной (предположим, что это не ТБ данных):
founddata=`find . -name "filename including space" -print0`
echo "$founddata" | xargs -0 ls -aldF > log.txt
echo "$founddata" | xargs -0 rm -rdf
Ответ 2
find . -name "filename including space" -print0 |
xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt; rm -rdf {}'
Ответ 3
Я считаю, что теперь все эти ответы дали правильные пути решения этой проблемы. И я попробовал 2 решения Джонатана и способ Гленна, все из которых отлично поработали на моей Mac OS X. Метод mouviciel не работал на моей ОС, возможно, из-за некоторых причин конфигурации. И я думаю, что это похоже на второй метод Джонатана (возможно, я ошибаюсь).
Как упоминалось в комментариях к методу Гленна, требуется небольшая настройка. Итак, вот команда, которую я пробовал, которая отлично работала FYI:
find . -name "filename including space" -print0 |
xargs -0 -I '{}' sh -c 'ls -aldF {} | tee -a log.txt ; rm -rdf {}'
Или лучше, как предложил Гленн:
find . -name "filename including space" -print0 |
xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt ; rm -rdf {}'
Ответ 4
Пока у вас нет новой строки в ваших именах файлов, вам не нужно -print0 для GNU Parallel:
find . -name "My brother 12\" records" | parallel ls {}\; rm -rdf {} >log.txt
Смотрите видеоролик, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ
Ответ 5
Просто вариация подхода xargs
без этих ужасных -print0
и xargs -0
, вот как я это сделаю:
ls -1 *.txt | xargs --delimiter "\n" --max-args 1 --replace={} sh -c 'cat {}; echo "\n"'
Сноска:
- Да, я знаю, что новые строки могут появляться в именах файлов, но кто в здравом уме будет это делать
- Есть короткие варианты для
xargs
, но для понимания читателем я использовал длинные.
- Я бы использовал
ls -1
, когда мне нужно нерекурсивное поведение, а не find -maxdepth 1 -iname "*.txt"
, которое немного более подробное.
Ответ 6
Вы можете выполнить несколько команд после find
с помощью for
вместо xargs
:
IFS=$'\n'
for F in `find . -name "filename including space"`
do
ls -aldF $F > log.txt
rm -rdf $F
done
IFS
определяет внутренний разделитель полей, который по умолчанию равен <space> < tab <newline> . Если ваши имена файлов могут содержать пробелы, лучше переопределить их, как указано выше.
Ответ 7
Я опаздываю на вечеринку, но есть еще одно решение, которое здесь не было описано: пользовательские функции. Наложение нескольких инструкций на одну строку громоздко и может быть трудно читать/поддерживать. Цикл for выше позволяет избежать этого, но есть вероятность превышения длины командной строки.
Здесь другой способ (непроверенный).
function processFiles {
ls -aldF "[email protected]"
rm -rdf "[email protected]"
}
export -f processFiles
find . -name "filename including space"` -print0 \
| xargs -0 bash -c processFiles dummyArg > log.txt
Это довольно просто, за исключением "dummyArg", который дал мне много горя. При запуске bash таким образом аргументы считываются в
"$0" "$1" "$2" ....
вместо ожидаемого
"$1" "$2" "$3" ....
Так как processFiles {} ожидает, что первый аргумент будет " $1", мы должны вставить фиктивное значение в " $0" .
Footnontes:
- Я использую некоторые элементы синтаксиса bash (например, export -f "), но я считаю, что это будет адаптироваться к другим оболочкам.
- В первый раз, когда я попробовал это, я не добавил фиктивный аргумент. Вместо этого я добавил " $0" в строки аргументов внутри моей функции (например, ls -aldf "$ 0" "$ @" ). Плохая идея.
Помимо стилистических проблем, он прерывается, когда команда find ничего не возвращает. В этом случае $0 устанавливается на "bash", используя фиктивный аргумент, вместо этого избегает всего этого.
Ответ 8
Другое решение:
find . -name "filename including space" -print0 \
| xargs -0 -I FOUND echo "$(ls -aldF FOUND > log.txt ; rm -rdf FOUND)"