Команда найти все файлы в каталоге и объединить их для параметра? - PullRequest
1 голос
/ 22 сентября 2010

Я ищу команду, которая находит все файлы в каталоге с использованием определенного компонента, позволяет сказать "* .txt" и создать список параметров из него в BASH.

Итак, если каталог содержит: file1.txt file2.txt file3.txt nonsense.c

Мне нужна строка "file1.txt file2.txt file3.txt"

Я знал, что для этого была команда BASH / Unix, но я не могу вспомнить: -S. "найти" не работает для меня ...

Спасибо!

Иван Янссенс

Ответы [ 6 ]

3 голосов
/ 22 сентября 2010

Если вы хотите выполнить команду для файлов, совпадающих с подстановочным знаком, вам не нужен дополнительный багаж:

mycommand *.txt

Что вы помните, это, вероятно, команда xargs.Он берет список имен файлов на своем стандартном входе и запускает команду для этих файлов.Например, echo *.txt | xargs mycommand - это сложный и ненадежный способ записи mycommand *.txt.xargs полезен, когда список файлов, с которыми mycommand должен работать, является выводом какой-либо другой команды.

Причина, по которой я сказал xargs, ненадежна в том, что она ожидает, что ее входные данные будут процитированысвоеобразным способом: все пробельные символы (не только переводы строк) разделяют имена, обратные слэши должны быть удвоены, а ' и " разграничивать буквенные строки (в которых только обратная косая черта и конечная кавычка являются специальными).Поскольку немногие команды выводят данные в формате ввода xargs, это ограничивает полезность xargs теми редкими случаями, когда известно, что имена файлов не будут содержать никаких специальных символов.

* 1020Команда * часто используется в сочетании с xargs, но этого следует и можно избежать.Вместо find ... | xargs mycommand напишите

find ... -exec mycommand {} +
2 голосов
/ 23 сентября 2010

Простой ответ:

mylist=$(ls *.txt)

ПРИМЕЧАНИЕ. Ls сообщает об ошибке, если ничего не найдено.Ошибки могут быть перенаправлены в /dev/null.

Для команд, отличных от ls и find, если совпадений нет, использование подстановочного знака обычно возвращает подстановочный знак в качестве результата;поэтому необходимо обрабатывать особый случай отсутствия совпадений.

Следующее устанавливает переменную "list" для всех файлов .txt или устанавливает ее в пустую строку, если таких файлов не существует.Преимущество перед ls (1) заключается в том, что if не вызывает никакой внешней команды.

list=$(echo *.txt)
if [ "$list" = "*.txt" ] ; then list=""; fi

Пример использования для запуска моей команды, но только если список не пуст:

test -n "$list" && my-command $list

Now,если в ваших файлах могут быть пробелы в именах, тогда лучше использовать массив:

List=()
let n=0
for x in *.txt
do
    test -e "$x" || exit
    List[n++]="$x"
done

Затем используйте список с

test ${#List[@]} -gt 0 && my-command "${List[@]}"

или

for value in "$List[@]" ; do my-command "$value" ; done 

Всеэто может немного отличаться для ksh, но это будет очень похоже.

2 голосов
/ 22 сентября 2010

Звучит так, как вы хотите ls и xargs.

1 голос
/ 22 сентября 2010

Вы запросили одну из самых основных функций любой оболочки Unix. По какой-то причине он известен как «глобализация» и встроен.

$ echo *.txt
0 голосов
/ 22 сентября 2010

Если вы просто ищете файлы в одном каталоге, а не во вложенных каталогах, вы можете использовать аргумент glob для вашей команды, который будет интерпретироваться оболочкой и выдавать один аргумент вашей команде длякаждое соответствующее имя файла:

$ echo *.txt
file1.txt file2.txt file3.txt

Если вы ищете файлы, произвольно вложенные глубоко в подкаталоги, find действительно то, что вы ищете.Вам нужно передать каталог, в котором вы ищите, и использовать параметр -name с выражением glob в кавычках, чтобы найти соответствующие файлы (если glob не указан в кавычках, оболочка попытается его интерпретировать и подставит списокфайлы, соответствующие этому имени в текущем каталоге, а это не то, что вам нужно):

$ find . -name "*.txt"
file1.txt. file2.txt file3.txt subdir/file.txt

Если вы хотите передать их в качестве аргументов другой функции, вы можете использовать $() (что эквивалентноболее знакомые обратные кавычки ``),

echo $(find . -name "*.txt")

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

find . -name "*.txt" | xargs echo

Если ваши имена файлов содержат пробелы, то xargs будетразделите их на две части, рассматривая каждый как отдельный аргумент, а это не то, что вам нужно.Вы можете избежать этого, используя нулевой символ 0 в качестве разделителя с аргументом -print0 для find и аргументом -0 для xargs.

find . -name "*.txt" -print0 | xargs -0 echo
0 голосов
/ 22 сентября 2010
$ echo "*.txt"
1.txt 2.txt ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...