Я хочу использовать find
найти файлы в ряде папок ограниченными подстановочными знаками, но где существуют пробелы в пути.
Из командной строки это легко. Следующие примеры вся работа.
find te*/my\ files/more -print
find te*/'my files'/more -print
find te*/my' 'files/more -print
Они найдут файлы в, например, terminal/my files/more
и tepid/my files/more
.
Однако мне нужно это, чтобы быть частью сценария; то, в чем я нуждаюсь, является чем-то вроде этого:
SEARCH='te*/my\ files/more'
find ${SEARCH} -print
К сожалению, независимо от того, что я делаю, я, кажется, не могу смешать подстановочные знаки и пробелы в a find
команда в рамках сценария. Вышеупомянутый пример возвращается, следующие ошибки (отметьте неожиданное удвоение обратной косой черты):
find: ‘te*/my\\’: No such file or directory
find: ‘files/more’: No such file or directory
Попытка использовать кавычки также перестала работать.
SEARCH="te*/'my files'/more"
find ${SEARCH} -print
Это возвращает следующие ошибки, проигнорировав значение кавычек:
find: ‘te*/'my’: No such file or directory
find: ‘files'/more’: No such file or directory
Вот еще один пример.
SEARCH='te*/my files/more'
find ${SEARCH} -print
Как ожидалось:
find: ‘te*/my’: No such file or directory
find: ‘files/more’: No such file or directory
Каждое изменение, которое я попробовал, возвращает ошибку.
У меня есть обходное решение, которое потенциально опасно, потому что оно возвращает слишком много папок. Я преобразовываю все пробелы в вопросительный знак (односимвольный подстановочный знак) как это:
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /?} # Convert every space to a question mark.
find ${SEARCH} -print
Это - эквивалент:
find te*/my?files/more -print
Это возвращает не только корректные папки, но также и terse/myxfiles/more
, который это, как не предполагается.
Как я могу достигнуть того, что я пытаюсь сделать? Google не помог мне :(
Та же самая команда должна хорошо работать в сценарии:
#!/usr/bin/env bash
find te*/my\ files/ -print
, Если Вы потребность для имения его как переменной это становится немного более сложным:
#!/usr/bin/env bash
search='te*/my\ files/'
eval find "$search" -print
Используя eval
как этот не безопасно и может привести к выполнению произвольного и возможно вредный код, если Ваши имена файлов могут содержать определенные символы. См. FAQ 48 удара для деталей.
лучше передать путь как аргумент:
#!/usr/bin/env bash
find "$@" -name "file*"
<час> Другой подход должен избежать find
в целом, и удар использования расширил globbing функции и шарики:
#!/usr/bin/env bash
shopt -s globstar
for file in te*/my\ files/**; do echo "$file"; done
globstar
опция удара позволяет Вам использовать **
для соответствия рекурсивно:
globstar
If set, the pattern ** used in a pathname expansion con‐
text will match all files and zero or more directories
and subdirectories. If the pattern is followed by a /,
only directories and subdirectories match.
, Чтобы заставить его действовать 100% нравится, находят и включают dotfiles (скрытые файлы), используют
#!/usr/bin/env bash
shopt -s globstar
shopt -s dotglob
for file in te*/my\ files/**; do echo "$file"; done
, Вы можете даже echo
их непосредственно без цикла:
echo te*/my\ files/**
Как насчет массивов?
$ tree Desktop/ Documents/
Desktop/
└── my folder
└── more
└── file
Documents/
└── my folder
├── folder
└── more
5 directories, 1 file
$ SEARCH=(D*/my\ folder)
$ find "${SEARCH[@]}"
Desktop/my folder
Desktop/my folder/more
Desktop/my folder/more/file
Documents/my folder
Documents/my folder/more
Documents/my folder/folder
(*)
разворачивает в массив любых соответствий подстановочный знак. И "${SEARCH[@]}"
расширяется во все элементы в массиве ([@]
), с каждым индивидуально заключенным в кавычки.
Запоздало, я понимаю, оказываются, должно быть способно к этому. Что-то как:
find . -path 'D*/my folder/more/'
Я наконец узнал ответ.
Добавляют обратную косую черту ко всем пробелам:
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /\\ }
На данном этапе SEARCH
содержит te*/my\ files/more
.
Затем используйте eval
.
eval find ${SEARCH} -print
Это настолько просто! Используя eval
обходы интерпретация, что ${SEARCH}
от переменной.