Comment échapper correctement des caractères bizarres dans un script bash?

Je ne suis pas professionnel dans les scripts ou trouve des commands quoi que ce soit (juste un avertissement). J'essaye de créer un script qui peut déplacer tous mes podcasts mp3 vers un dossier que je peux ensuite déplacer vers mon téléphone.

Donc, le script que j'ai fait doit déplacer tous les mp3 (même ceux avec des paths bizarres). J'ai créé un script comme suit et il semble * faire ce que je voulais, mais il continue à donner des erreurs comme suit:

find /home/jason/gPodder/ -name '*.mp3' -exec bash " cp '{}' /home/jason/gPodder/mp3/ " \; Which returns: bash: cp '/home/jason/gPodder/Downloads/The Documentary/TheDocumentary20170823-GoingGreenInTheOilState.mp3' /home/jason/gPodder/mp3/ : No such file or directory 

Mais si je copy la command ci-dessus bash 'il ne fonctionne pas. S'il vous plaît pourriez-vous m'aider à comprendre ce que mon erreur est dans le script.

Je vous remercie

Comme l'a dit @Kusalananda , il vous manque un -c pour pouvoir utiliser un script en ligne.

Mais même alors, n'intégrez jamais le {} dans le code du shell, ce serait une vulnérabilité arbitraire d'injection de commands (pensez par exemple à un file nommé '$(reboot)'.mp3 ). Au lieu de cela faire un argument du script en ligne (en supposant que vous avez besoin d'un script en ligne ici et que le cp est juste un exemple).

 find ... -exec sh -c 'cp "$1" /home/jason/gPodder/mp3' sh {} \; 

(vous n'avez pas non plus besoin de bash juste pour ça, votre sh fera tout aussi bien).

Ou encore mieux, passer plusieurs arguments à la fois à cp :

 find ... -exec sh -c 'cp "$@" /home/jason/gPodder/mp3' sh {} + 

Avec GNU cp , vous pouvez aussi le faire:

 find ... -exec cp -t /home/jason/gPodder/mp3 {} + 

Ne le rends pas plus compliqué que nécessaire.

 find /home/jason/gPodder/ -name '*.mp3' -exec cp {} /home/jason/gPodder/mp3/ \; 

ou éventuellement

 find /home/jason/gPodder/ -type f -name '*.mp3' -exec cp {} /home/jason/gPodder/mp3/ \; 

pour ne considérer que les files réguliers.

Pour copyr uniquement le file si aucun file portant le même nom n'existe déjà dans le dossier de destination:

 find /home/jason/gPodder/ -type f -name '*.mp3' \ -execdir test -e /home/jason/gPodder/mp3/{} \; \ -exec cp {} /home/jason/gPodder/mp3/ \; 

-execdir est une extension de la find standard POSIX, mais est supporté par de nombreuses implémentations de find modernes. Il exécute comme -exec mais exécute la command avec le directory parent de la chose trouvée comme son directory de travail. En outre, {} sera le nom de base de la chose trouvée plutôt que le path complet de celle-ci. Voir l' man find .


L'erreur provient de bash "somecommand" . Lors de l'appel de bash , bash s'attend à somecommand que somecommand soit un script, pas une série de commands shell, et qu'il ne trouve pas de script avec le nom que vous lui donnez. Pour exécuter une série arbitraire de commands shell, vous avez besoin de bash -c "somecommand" .

Mais, dans ce cas, utilisez simplement -exec cp comme ci-dessus ou comme dans la réponse de Stéphane Chazelas .

D'autres ont souligné les problèmes de citation et d'exécution.

Je vais vous suggérer de ne pas utiliser find -exec, mais plutôt de find une list de files, et de placer cette list sur xargs et cp. L'utilisation de l'option print0 vous aidera à contourner les caractères "drôles" dans les noms de files et de directorys

par exemple

 find sourcepath -name \*.mp3 -print0 \ | xargs -0 cp -t destinationpath 

L'avantage de ceci est que xargs collectera plusieurs noms de files à partir de find et les transmettra à cp en même time afin que chaque instance de cp puisse copyr 20 ou 100 files au lieu de lancer une invocation de 1 cp pour chaque file. xargs veillera à insert suffisamment de noms de files dans la command line cp pour vous.

Vous pouvez également append l'option -P n à xargs et lancer plusieurs process cp en parallèle.

Sur la base que vos files sont sur le même système de files que le dossier mp3 de destination. Vous pouvez append -l à cp et il sera difficile de lier les files dans la destination, au lieu de les copyr.

par exemple

 find sourcepath -name \*.mp3 -print0 \ | xargs -0 -P 5 \ cp -l -t destinationpath