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

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

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

  • Как я могу печатать только переменные, определенные внутри моего сценария оболочки?
  • Сценарий для разбора полей
  • Использовать piped stdin в качестве аргумента для следующей команды
  • Замена строк в файле с использованием разных значений для замены одного и того же шаблона
  • Предотвратить расширение glob в foo = "*"; echo $ foo
  • Переименование файлов в локальной папке с добавлением префикса или суффикса
  • Как передать вывод одной команды в качестве аргумента командной строки другому?
  • Как сделать svn сохранить учетные данные, когда --non-interactive
  • 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}'/) 

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

    Linux и Unix - лучшая ОС в мире.