J'essayais simplement de répertorier tous les répertoires et fichiers sous le répertoire actuel et d'écrire également s'ils sont des fichiers ou des répertoires avec la commande suivante:
find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;
Je sais que c'est une commande stupide, je peux utiliser d'autres choses comme -type f
ou -type d
, mais je veux savoir pourquoi ce morceau de code n'a pas fonctionné comme je m'y attendais. Il imprime simplement un répertoire à chacun d'eux. Par exemple, alors que la sortie de find
est:
.
./dir
./dir/file
la sortie de mon code est:
. : directory
./dir : directory
./dir/file : directory
Et sortie de
echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`
est
dir/file : file
Je travaille Ubuntu 14.10
et utilisefind (GNU findutils) 4.4.2
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
"{}"
. Pourquoi utilisez-vousecho
deux fois?echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi
\;Réponses:
Tout d'abord, votre extrait de code exécute la commande
car il a besoin de sa sortie pour évaluer la substitution de commande. Puisqu'il n'y a aucun fichier nommé
{}
, cela produit la sortieEnsuite , la
find
commande est exécutée avec les arguments-exec
,echo
,{}
,:
,directory
, donc pour chaque fichier, il affiche le nom du fichier suivi d'un espace et: directory
.Ce que vous voulez réellement faire, c'est exécuter l'extrait de shell
echo {} :; …
sur chaque fichier trouvé parfind
. Cet extrait doit être exécuté par un shell généré parfind
, et non par le shell qui démarrefind
, car il reçoit des données defind
sa ligne de commande. Par conséquent, vous devez demanderfind
à exécuter un shell:C'est mieux, mais toujours pas juste. Cela fonctionnera avec certaines (pas toutes)
find
implémentations si vos noms de fichiers ne contiennent pas de caractères spéciaux, mais comme vous interpolez le nom de fichier dans un script shell, vous autorisez les noms de fichiers à exécuter des commandes shell arbitraires, par exemple si vous avez un fichier appelé$(rm -rf /)
alors la commanderm -rf /
sera exécutée. Pour passer des noms de fichiers au script, passez-les comme arguments séparés.Le premier
echo
imprime également une nouvelle ligne après les deux points. Utilisezecho -n
(si votre shell le supporte) ouprintf
pour éviter cela.Vous pouvez utiliser
-exec … {} +
pour regrouper les invocations de shell, ce qui est plus rapide.la source
Une autre façon d'exécuter
if; then; else; fi
avecfind
:la source