У меня проблема с этим простым сценарием (выберите случайный файл):
#!/usr/bin/env bash
set -x
srcDir="/home/user/Desktop/wallPapers/{dir1,dir2,dir3}"
randomFile=$(find "$srcDir" -type f -iname "*.jpg" | shuf -n 1)
printf '[%s]\n' $randomFile
set +x
Проблема в том, что, хотя я могу набрать это в командной строке (и работает отлично):
find /home/user/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg"
Затем команды set для отладки bash (set -x и + x) сообщают мне, что по какой-то причине bash включает строку каталога с одинарными кавычками, а также заменяет двойные кавычки одинарными кавычками отмечает?
./script.sh
+ srcDir='/home/user/Desktop/wallPapers/{dir1,dir2,dir3}'
++ find '/home/user/Desktop/wallPapers/{dir1,dir2,dir3}' -type f -iname '"*.jpg"'
find: ‘/home/user/Desktop/wallPapers/{dir1,dir2,dir3}’: No such file or directory
+ randomFile=
+ printf '[%s]\n'
[]
+ set +x
Я понимаю, это то, что видит bash при запуске скрипта:
find '/home/user/Desktop/wallPapers/{dir1,dir2,dir3}' -type -iname '*.jpg'
И это вызывает сообщение «Нет такого файла или каталога», очень очень раздражает ... я не понимаю, почему он вставляет эти одинарные кавычки, я хочу использовать вместо них двойные кавычки, как в командной строке ... Может кто-нибудь объяснить, я был бы рад за это, спасибо!
Расширение фигурных скобок не происходит в пределах присваивания переменной, как объяснено здесь:
Почему префиксы тильды расширяются до назначения, а фигурные скобки - нет
В других контекстах кавычки также предотвратили бы расширение скобки.
Даже если вам удастся расширить srcDir
до списка каталогов, повторное цитирование его в команде find
приведет к тому, что он будет рассматриваться как один аргумент вместо 3 отдельных путей.
Вероятно, правильным способом сделать это в bash является использование массива:
#!/usr/bin/env bash
set -x
srcDir=("/home/user/Desktop/wallPapers/"{dir1,dir2,dir3})
randomFile=$(find "${srcDir[@]}" -type f -iname "*.jpg" | shuf -n 1)
printf '[%s]\n' "$randomFile"
set +x
Как уже отмечали другие, кавычки препятствуют расширению фигурной скобки. Вы можете упростить ваш скрипт до:
#!/usr/bin/env bash
printf '[%s]\n' "$(find /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg" | shuf -n 1)"
Или, если ваши имена файлов могут содержать символы новой строки:
#!/usr/bin/env bash
printf '[%s]\n' "$(find /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg" -print0| shuf -zn 1)"
Если вы хотите что-то, что может работать на произвольных каталогах и типах файлов попробуйте это:
#!/usr/bin/env bash
targetFilePattern="$1"
shift
declare -a targetDirs=("$@")
echo "find ${targetDirs[@]} -type f -iname '$targetFilePattern' | shuf -n 1"
randomFile=$(find "${targetDirs[@]}" -type f -iname "$targetFilePattern" | shuf -n 1)
echo "$randomFile"
Затем вы можете запустить его как:
printRandomFile '*jpg' /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3}
Или даже
printRandomFile '*jpg' /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3,'a dir with a space'}
Расширение фигурных скобок не выполняется внутри двойных кавычек. Есть дублирующий вопрос относительно этого где-то. Кроме того, используйте флаг -printf для поиска, выполнять подстановку команд не нужно, поэтому вы можете сделать это
find /home/user/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg" -printf '[%f]\n' | shuf -n1