Как построить пространство в отдельности, избегать полных путей файлов, рекурсивно сопоставляющих glob?

У меня есть программа, которая требует путей к файлам в качестве аргументов, которые не могут быть указаны и не должны зависеть от рабочего каталога. Можно ли это сделать без xargs нескольких xargs , tr , find , readlink s?

Пример вывода для файлов «* .csv»: /home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv

2 Solutions collect form web for “Как построить пространство в отдельности, избегать полных путей файлов, рекурсивно сопоставляющих glob?”

Для передачи путей к файлам в качестве аргументов для команды find делает это самостоятельно с параметром -exec без каких-либо xargs :

 find /home/user -name '*.csv' -exec yourcommand '{}' + 

Это найдет каждый файл с именем *.csv в /home/user а затем выполнит yourcommand /home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv ... со всеми найденные файлы в качестве аргументов. Каждый найденный файл передается в виде отдельного полного аргумента в программу, поэтому не требуется экранирование или что-то еще: yourcommand много аргументов, каждый из которых соответствует полному пути к файлу.

Другой подход заключается в том, что некоторые оболочки ( в частности, zsh ) поддерживают более продвинутое подталкивание, где вы можете просто написать:

 yourcommand **/*.csv 

и получить точно такой эффект.


Если вам действительно нужны экранированные строки , а не для запуска команды напрямую, вы можете использовать встроенный printf bash :

 find /home/user -name '*.csv' -exec bash -c 'printf "%q " "$@"' dummy '{}' + 

Спецификация формата %q расширяется до версии строкового аргумента, экранированной оболочкой. С многими аргументами printf повторяет строку формата для всех из них, поэтому это приводит к экранированным экранированным по нескольку строк всех аргументов команде bash -c . dummy используется как значение $0 , а "$@" дает printf все остальные аргументы, которые являются вашими (неповрежденными) именами файлов. Для вашего примера это будет выводить точно /home/user/a\ b.csv /home/user/my\ dir/c\ d\$2.csv .

С zsh :

 print -r -- **/*.csv(D:a:q) 

Обратите внимание, что некоторые символы (например, символы новой строки, вкладки или непечатаемые) отображаются с обозначением $'...' которое может быть проблемой для вас.

Другой подход:

 print -r -- *.csv(e/'REPLY=${(qq)REPLY:a}'/) 

Там, где все пути к файлам имеют одинарные кавычки.

  • Заменить переменную цикла в шаблоне строки
  • Интерпретация Backquotes
  • Выберите добавленные строки из файла
  • Почему «$ i | sed "не работает?
  • Извлечь имя базового файла из URL с помощью bash
  • Могу ли я поставить более одного условия, если?
  • bash: синтаксическая ошибка около неожиданного токена `} '
  • Почему zsh открывает дескриптор файла одним?
  • Как получить вчерашнюю дату и сохранить в одной переменной
  • Почему переменная $ PATH отличается между двумя каталогами?
  • Как установить размер окна и местоположение приложения на экране с помощью командной строки?
  • Развернуть подоболочку перед ее выполнением?
  • Linux и Unix - лучшая ОС в мире.