Я хочу использовать, 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
К сожалению, что бы я ни делал, я не могу смешивать подстановочные знаки и пробелы в 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
, что это не должно.
Как я могу достичь того, что я пытаюсь сделать? Гугл мне не помог :(
SEARCH: command not found
командаfind -print
выполняется.find "${SEARCH}" -print
?te*/'my files'/more
.Ответы:
Точно такая же команда должна нормально работать в скрипте:
Если вам нужно иметь его как переменную, он становится немного сложнее:
ПРЕДУПРЕЖДЕНИЕ:
Такое использование
eval
небезопасно и может привести к выполнению произвольного и, возможно, вредоносного кода, если имена ваших файлов могут содержать определенные символы. Смотрите bash FAQ 48 для подробностей.Лучше передать путь в качестве аргумента:
Другой подход заключается в том, чтобы
find
вообще избежать и использовать расширенные функции и глобусы bash:Опция
globstar
bash позволяет использовать**
для рекурсивного соответствия:Чтобы заставить его действовать на 100%, как находить и включать точечные файлы (скрытые файлы), используйте
Вы можете даже
echo
их напрямую без цикла:источник
Как насчет массивов?
(*)
расширяется в массив того, что соответствует шаблону. И"${SEARCH[@]}"
распространяется на все элементы в массиве ([@]
), каждый из которых заключен в кавычки.С опозданием, я понимаю, найти себя должен быть способен на это. Что-то вроде:
источник
INPUTPATH='te*/my files/more
иSEARCH=(${INPUTPATH})
. Независимо от того, как я изменяю способ, которым я делаю это, я все равно получаю нефункциональный результат. Это кажется невозможным!find
«s-path
фильтр? Он использует подстановочные знаки и определенно не нуждается в расширении.-path
. Однако за последние 10 минут я понял ответ: пользуйсяeval
! Кажется, это проще, чем-path
.Я наконец-то узнал ответ.
Добавьте обратную косую черту ко всем пробелам:
На данный момент,
SEARCH
содержитte*/my\ files/more
.Затем используйте
eval
.Это так просто! Использование
eval
обходит интерпретацию${SEARCH}
из переменной.источник