Как передать строки, сохраненные в переменных для нахождения команды

Я должен передать строки, сохраненные в переменной к командной строке находки.

Что я делаю:

s="\( ! -path \"/path/to/1/Recycle Bin\" \) -or"
s="${s} \( ! -path \"/path/to/2/Recycle Bin\" \)"
exec=$(find "/path/to/Recycle Bin" -type d $s)

Результат:

find: paths must precede expression: `\('

Если я делаю:

exec=$(find "/path/to/Recycle Bin" -type d \( ! -path "/path/to/1/Recycle Bin" \) -or \( ! -path "/path/to/2/Recycle Bin" \))

Работает.

Что я делаю неправильно?

1
задан 12 December 2018 в 18:15

2 ответа

По моему скромному мнению, единственное надежное, чтобы сделать это в ударе должно использовать массив.

Правильно заключенные в кавычки массивы позволяют Вам создавать командную строку, которая состоит из индивидуально parsable аргументов, которые могут содержать пробел.

Напр.

$ a=( find "/path/to/Recycle Bin" -type d )
$ a+=( \( ! -path "/path/to/1/Recycle Bin" )
$ a+=( -or ! -path "/path/to/2/Recycle Bin" \) )

Мы видим то, что оболочка будет видеть путем распечатывания отдельных элементов, один на строку:

$ printf '%s\n' "${a[@]}"
find
/path/to/Recycle Bin
-type
d
(
!
-path
/path/to/1/Recycle Bin
-or
!
-path
/path/to/2/Recycle Bin
)
1
ответ дан 7 December 2019 в 15:10

Если Ваша переменная не могла бы содержать то, что Вы думаете, что она делает, использует

set -x

видеть результат каждого расширения.

Оболочка обрабатывает обратные косые черты и двойные кавычки в find команды, но это не обрабатывает их тот же путь, когда это разворачивает Вашу переменную...

На командной строке мы пишем:

find "/path/to/Recycle Bin" -type d \( ! -path "/path/to/1/Recycle Bin" \) -or \( ! -path "/path/to/2/Recycle Bin" \)

Если Вы работали set -x, Вы видите то, что Bash делает из этого и что на самом деле передается find:

+ find '/path/to/Recycle Bin' -type d '(' '!' -path '/path/to/1/Recycle Bin' ')' -or '(' '!' -path '/path/to/2/Recycle Bin' ')'

Удаления кавычки на Вашей переменной не происходит (Вы помещаете \ и " символы там, таким образом, Вы хотите их сохраненный, правильно? Они изображают, "следовали из расширения", таким образом, они не удалены) (\" стал " когда Вы присвоили его, как Вы, по-видимому, предназначили, потому что в двойных кавычках обратная косая черта заключает символы в кавычки \$`"), но wordsplitting делает:

$ find "/path/to/Recycle Bin" -type d $s
+ find '/path/to/Recycle Bin' -type d '\(' '!' -path '"/path/to/1/Recycle' 'Bin"' '\)' -or '\(' '!' -path '"/path/to/2/Recycle' 'Bin"' '\)'
find: paths must precede expression: \(

Заключение в кавычки переменной фиксирует разделение ругательства, но также и предотвращает токенизацию:

$ find "/path/to/Recycle Bin" -type d "$s"
+ find '/path/to/Recycle Bin' -type d '\( ! -path "/path/to/1/Recycle Bin" \) -or \( ! -path "/path/to/2/Recycle Bin" \)'
find: paths must precede expression: \( ! -path "/path/to/1/Recycle Bin" \) -or \( ! -path "/path/to/2/Recycle Bin" \)

В значительной степени что-либо, что Вы делаете с этими двумя строками, собирается привести к find наблюдение неправильной вещи. Получение переменной содержать только и точно строка, которая расширяется до '(' '!' -path '/path/to/1/Recycle Bin' ')' -or '(' '!' -path '/path/to/2/Recycle Bin' ')' война кавычки, которую я лично не мог выиграть.

Что-то вроде этого будет хорошо работать

s="/path/to/1/Recycle Bin"
t="/path/to/2/Recycle Bin"
find "/path/to/Recycle Bin" -type d \( ! -path "$s" \) -or \( ! -path "$t" \)

Можно также выйти сухим из воды, если Вы устраняете необходимость заключения в кавычки, не используя пути с пробелами - при вынимании обратных косых черт и двойных кавычек:

s="( ! -path /path/to/1/Trash ) -or"
s="${s} ( ! -path /path/to/2/Trash )"
find /path/to/Trash -type d $s

Возможно, если Вы объясняете, почему Вы хотите сделать это этот путь, кто-то может предложить лучшее обходное решение.

0
ответ дан 7 December 2019 в 15:10

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

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