Intereting Posts
Вывести реальное имя сервиса во время загрузки с помощью systemd Как запустить цепочку процессов из оболочки Что общего у BSD? Беспроводной адаптер исчезает при переводе в режим монитора Как предоставить sftp доступ к подкаталогу только не к родительскому Как включить сторожевой таймер? gtk-window-decorator занимает слишком много памяти, и можно ли перезагрузить его? использовать результат поиска взамен инструкции с заменой vim Может ли btrfs обрабатывать разные уровни RAID для разных подвыборов? Автоматическое монтирование других разделов в Arch Linux Awk разделяет большой файл условно в нескольких выходных файлах Пользователь Netatalk как в rwlist, так и в rolist Одиночная машина с двумя дисками startx выдает ошибку «Не удалось разрешить keysym XF86 KeyboardError» Из сценария bash существует ли способ получить привязку клавиш для «окна изменения размера»?

Как перечислять имена файлов, которые содержат пробелы и специальные символы, без использования find

Я пишу сценарий, который требует от меня предоставить список файлов в моем каталоге, имена файлов которых содержат пробелы, *,?, $,% И т. Д. Как я могу это сделать, я видел несколько сообщений, но не мог найти ничего, что сработает для меня. Можно ли добиться этого с помощью grep?

grep -E должен делать то, что вам нужно. Обратите внимание, что некоторые символы должны быть экранированы с обратной косой чертой, поэтому, если вы добавите больше, а результаты не то, что вы ожидали, убегите и повторите попытку. Обратите внимание на | это or

 $ ls | grep -E '\s|\*|\?|\$|%' all this.txt all?this.txt all*this.txt all%this.txt all th*s.txt all$.txt 
 printf '<%s>\n' *[[:space:]*?$%]* 

Он не будет сообщать о скрытых файлах. Будет ли [[:space:]] соответствовать многобайтовым символам интервала (например, " " ( EM QUAD ) в UTF-8) зависит от вашей оболочки (некоторые вроде dash не являются многобайтовыми символами)

Пример:

 $ touch sane 'a%b' $'with\nnewline' $'with space' $'with em-quad' $ printf '<%s>\n' *[[:space:]*?$%]* <a%b> <with em-quad> <with newline> <with space> 

Безопасный список файлов создается без кавычек * , не используется:

 $ echo * 

Давайте проверим несколько файлов:

 $ mkdir test-dir; cd test-dir $ touch clean normal_file 'a%b' 'has two spaces' '*' 'a*b' '?' 'a?b' $ touch '$' 'a$b' '%' 'a%b' $'new\nline' $'em\u2001quad' 'normal_file' 

Команда echo * будет производить с файлами выше:

 ? $ * % a?ba$ba*ba%b clean em quad has two spaces new line normal_file 

Список, разделенный пробелом, который, да, имеет две строки, так как есть файл с новой строкой в ​​его имени.

Более простой способ увидеть файлы – процитировать их имя с помощью printf '%q' и добавить новую строку, например printf '%q\n' мы получим чистый список файлов:

 $ printf '%q\n' * \? \$ \* % a\?b a\$b a\*b a%b clean $'em\342\200\201quad' has\ two\ spaces $'new\nline' normal_file 

Конечно, вам нужно выбрать некоторые файлы, а не все, как с простым *.
Таким образом, мы создаем шаблон всех символов в соответствии с ?$*% .
Однако большинство этих символов являются «специальными» и требуют кавычек, когда они появляются в некоторых заказах. В частности, если * или ? следует за $ , они расширяются оболочкой, что может создать проблемы.
Крайне важно процитировать $ .
Тогда, простой способ получить все остальные символы, цитируемые, это использовать printf '%q' ?\$*% . Это произведет: \?\$\*% . Если обратная косая черта не является строго необходимой, она не будет иметь плохого эффекта, беглый символ все равно будет работать.
В этот список нам нужно добавить несколько пробелов. Но включение новой строки становится серьезной проблемой. Самый простой способ справиться с новой строкой внутри символьного класса – использовать [[:space:]] , который будет включать в себя символы новой строки, пробела, табуляции и некоторые другие символы пробела как em-dash.

Поэтому команда становится:

 $ printf '%q\n' *[\?\$\*%[:space:]]* \? \$ \* % a\?b a\$b a\*b a%b $'em\342\200\201quad' has\ two\ spaces $'new\nline' 

Обратите внимание, что normal_file файлов clean и normal_file списке не указаны.

Это очень просто и работает уже с Bourne Shell с 1979 года:

 for i in * do case "$i" in *\ *) echo blank $i;; *\?*) echo qmark $i;; esac done 

в одной строке:

 for i in *; do case $i in *\ *|*\?*|*\**|*\$*|*%* ) echo "Special character $i"; ;; * ) echo "normal file $i"; ;; esac done 

Добавьте больше случаев, если хотите …