J'ai un problème, avec ce simple script (choisissez un fichier aléatoire):
#!/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
Le problème est que même si je peux taper ceci sur la ligne de commande (et fonctionne parfaitement bien):
find /home/user/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg"
Ensuite, les commandes set de débogage bash (set -x et + x) m'indiquent que, pour une raison quelconque, bash enferme la chaîne de répertoire avec des guillemets simples et remplace également les guillemets doubles par des guillemets simples.
./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
Je comprends, c'est ce que voit bash, lorsque le script s'exécute:
find '/home/user/Desktop/wallPapers/{dir1,dir2,dir3}' -type -iname '*.jpg'
Et cela provoque le message "No such file or directory", très très ennuyeux ... Je ne comprends pas, pourquoi il insère ces guillemets simples, je veux des guillemets doubles à la place, tout comme sur la ligne de commande ... Quelqu'un pourrait-il expliquer, je serais heureux pour cela, merci!
L'expansion d'accolade ne se produit pas dans une affectation de variable, comme expliqué ici:
Pourquoi les préfixes tilde se développent avant l'affectation, mais pas les accolades
Dans d'autres contextes, les citations auraient également empêché l'expansion de l'accolade.
Même si vous parvenez à obtenir srcDir
à développer dans une liste de répertoires, en le citant à nouveau dans la commande find
, il sera traité comme un seul argument au lieu de 3 chemins distincts.
La bonne façon de faire cela dans bash est probablement d'utiliser un tableau:
#!/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
Comme d'autres l'ont déjà souligné, les citations empêchent l'expansion de l'accolade. Vous pouvez simplifier votre script pour simplement:
#!/usr/bin/env bash
printf '[%s]\n' "$(find /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg" | shuf -n 1)"
Ou, si vos noms de fichiers peuvent contenir des caractères de nouvelle ligne:
#!/usr/bin/env bash
printf '[%s]\n' "$(find /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg" -print0| shuf -zn 1)"
Si vous voulez quelque chose qui peut s'exécuter sur des répertoires et des types de fichiers arbitraires, essayez ceci:
#!/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"
Vous pouvez ensuite l'exécuter en tant que:
printRandomFile '*jpg' /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3}
Ou même
printRandomFile '*jpg' /home/terdon/Desktop/wallPapers/{dir1,dir2,dir3,'a dir with a space'}
L'expansion d'accolade n'est pas effectuée à l'intérieur de guillemets doubles. Il y a une question en double à ce sujet quelque part. En outre, utilisez l'indicateur -printf pour rechercher, la substitution de commandes n'est pas nécessaire, vous pouvez donc le faire
find /home/user/Desktop/wallPapers/{dir1,dir2,dir3} -type f -iname "*.jpg" -printf '[%f]\n' | shuf -n1