Я хочу сделать что-то несколько раз в списке файлов. У файлов в вопросах есть пробелы в их именах:
david@david: ls -l
total 32
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha
-rw-rw-r-- 1 david david 0 Mai 8 11:55 haha~
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (3rd copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (4th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (5th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (6th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (7th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (another copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (copy)
Теперь я хочу оценить каждый из этих файлов:
david@david: echo '
for file in $(ls)
do
stat $file
done' | bash
(Я использую echo и pipe для написания многострочных команд.)
Когда я это делаю, он корректно работает с теми файлами, в именах которых нет пробелов. Но остальные ...
stat: cannot stat ‘(another’: No such file or directory
stat: cannot stat ‘copy)’: No such file or directory
Изменение $(ls)
к "$(ls)"
или $file
к "$file"
не работает. Что я могу сделать?
Редактировать:
echo '
for files in *
do
stat "$files"
done' | bash
делает трюк! Поскольку я новичок в bash, я хочу, чтобы все было как можно проще - не пытаясь избежать пробелов, использовать xargs
или read -r
решить их, хотя они решают проблему.
Как некоторые спрашивают: да, использовать это вместо stat *
странно. Но я просто хотел найти общий способ применения одной и той же команды к группе имен файлов в bash, используя цикл for. Так stat
может стоять gzip
, gpg
или rm
.
источник
stat *
? (;-)Ответы:
Многократная цитата из
echo '
усложняет вещь.Вы можете просто использовать:
Но и
... и если вы хотите собрать файлы и затем применить команду (почему?), вы можете пойти (но будьте осторожны с файлом, содержащим новые строки ... (1))
... и если вы хотите скрытые файлы, просто используйте
* .*
в качестве шаблона, но затем помните, что.
и..
будет в наборе .Кроме того, вы не должны анализировать
ls
вывод .(1) но если у вас есть имена файлов с символами новой строки, вы это заслужили ... ;-)
источник
for f in *; do command "$f"; done
. Никогда не разбирайтеls
, конечно, никогда не делайте это вfor
цикле и зачем использоватьecho
?do
,|
, и&&
т.д., вы можете продолжить на новой линии. Либо так, либо используйте heredocs. Нет причин для использования,echo
и это также может вызвать проблемы.На заметку: вы можете разделить длинные / сложные команды на несколько строк, добавив пробел с обратной косой чертой и нажимая Enterкаждый раз, когда вы хотите начать запись в новую строку, вместо того, чтобы разбивать несколько процессов с помощью
echo [...] | bash
; также вы должны заключить$file
в двойные кавычки, чтобы предотвратитьstat
разрыв в случае имен файлов, содержащих пробелы:Проблема в том, что
$(ls)
расширяется список имен файлов, содержащих пробелы, и то же самое произойдет и с"$(ls)"
.Даже решая эту проблему, этот метод будет разбивать имена файлов, содержащие обратную косую черту, и имена файлов, содержащие символы новой строки (как указал тердон).
Решение для обеих задач было бы трубы выход
find
кwhile
петле работаетread -r
так , что на каждой итерации,read -r
будет хранить одну строкуfind
«с выходом в$file
:источник
ls
. Когда-либо.ls
. Есть лучшие и более надежные способы. Вы также можете прочитать это: почему * not * parse `ls`? Больше подробностей.ls
, этоfor
-for
перебирает (МФС отделенный) слова даны послеin
keyword`for
иls
.for f in *
было бы хорошо, например.Используйте старый добрый
find
, работает со скрытыми файлами, переводами строки и пробелами.или любой другой вместо
stat
источник
Как парень из R, я уже нашел обходной путь в R:
Я знаю, это безумие. Хотелось бы, чтобы выходные данные
ls
было легче проанализировать ... R может иметь дело с пробелами, потому что dir () возвращает значение в кавычках. Все, что находится в кавычках, является допустимым именем файла с пробелами.источник
for f in *
, нажмите Enter и продолжите новую строку:do
нажмите сноваstat "$f"
Enter, сноваdone
введите Enter. Это команда, разделенная на 4 строки, которая не разбивается ни на какие имена файлов.Я сталкивался с другими случаями проблем с пробелами в циклах for, поэтому я обычно использую следующую (более надежную) команду. Это также хорошо вписывается в трубы.
Вы можете комбинировать это с
grep
или использоватьfind
вместо:источник
-E
параметрgrep
, без которого он не будет распознаваться+
в регулярном выражении. Даже тогда, это вопрос, который вы пропустили, поскольку выgrep
удаляете имена файлов, содержащие пробелы . Он также удаляет имена файлов, содержащие цифры (цифры) и знаки препинания (например, круглые скобки), как это делают примеры в вопросе. И это даже не упоминает имена файлов, которые содержат новую строку или начинаются с-
(тире).Этот ответ решит проблему разбора
ls
и позаботится о пробелах и новых строкахПопробуйте, это решит вашу проблему с помощью внутреннего разделителя полей IFS.
Но также вы можете легко решить эту проблему, не анализируя вывод ls, используя
источник
IFS
здесь: кавычки переменной должно быть достаточно, чтобы предотвратить разделение слов, не так ли?ls
.Вместо этого вы можете переименовать ваши файлы, заменив пространство другим символом, например подчеркиванием, так что вы избавитесь от этой проблемы:
Для этого легко запустите команду:
источник