Я должен передать строки, сохраненные в переменной к командной строке находки.
Что я делаю:
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" \))
Работает.
Что я делаю неправильно?
По моему скромному мнению, единственное надежное, чтобы сделать это в ударе должно использовать массив.
Правильно заключенные в кавычки массивы позволяют Вам создавать командную строку, которая состоит из индивидуально 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
)
Если Ваша переменная не могла бы содержать то, что Вы думаете, что она делает, использует
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
Возможно, если Вы объясняете, почему Вы хотите сделать это этот путь, кто-то может предложить лучшее обходное решение.