Как передать '*', подстановочный знак для соединения каналом параметра находки управляет через переменную в сценарии?

Я хочу использовать 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 не помог мне :(

8
задан 21 November 2014 в 03:15

3 ответа

Та же самая команда должна хорошо работать в сценарии:

#!/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/**
8
ответ дан 23 November 2019 в 05:38

Как насчет массивов?

$ 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/'
2
ответ дан 23 November 2019 в 05:38

Я наконец узнал ответ.

Добавляют обратную косую черту ко всем пробелам:

SEARCH='te*/my files/more'
SEARCH=${SEARCH// /\\ }

На данном этапе SEARCH содержит te*/my\ files/more.

Затем используйте eval.

eval find ${SEARCH} -print

Это настолько просто! Используя eval обходы интерпретация, что ${SEARCH} от переменной.

0
ответ дан 23 November 2019 в 05:38

Другие вопросы по тегам:

Похожие вопросы: