2016-12-21 1 views
0

Dans un script bash je suis en train d'utiliser le contenu d'une variable à utiliser comme options pour la commande find:Comment utiliser le contenu de la variable dans bash pour passer à trouver dans le script?

#!/bin/bash 
FILE_EXTENSIONS=(txt png jpg) 

FIRST=1 
for FILE_EXTENSION in ${FILE_EXTENSIONS[@]} 
do 
# echo "$FILE_EXTENSION" 
    if [[ $FIRST == 1 ]] 
    then 
     FIND_FILTER="-iname '*.$FILE_EXTENSION'" 
     FIRST=0 
    else 
     FIND_FILTER="${FIND_FILTER} -o -iname '*.$FILE_EXTENSION'" 
    fi 
done 
# Read and write only for user and group, ignore case '-iname' 
#find . -type f "$FIND_FILTER" -exec chmod 660 {} \; 
echo Find filter: $FIND_FILTER 
# This might work with some already provided suggestions: 
find . -type f $FIND_FILTER 
# But this fails so far 
find . -type f $FIND_FILTER -exec chmod 660 {} \;   
#EOF 

L'objectif est de définir des droits d'accès appropriés que pour une raison quelconque tout à fait certains fichiers (tels que des images ou des documents de bureau) sont marqués exécutable.

Donc en réalité le script ci-dessus a plusieurs tableaux avec des extensions de fichiers concaténées, mais le script montre le problème.

La première approche aurait consisté à parcourir à chaque fois le tableau final et la recherche d'appel. Mais d'un point de vue de l'exécution, il serait stupide de chercher à chaque fois encore et encore.

Je pourrais aussi simplement faire ceci en python mais pour une fois j'ai pensé que je voudrais le résoudre avec des moyens basiques de Linux dans bash.

Il semble que le contenu de la variable FIND_FILTER soit correct (au moins ce qui est imprimé avec echo) mais alors ... cela ne fonctionne pas.

Des suggestions? Qu'est-ce qui ne va pas?

Répondre

0

Vous avez commencé à utiliser des tableaux (presque) correctement, mais vous les avez abandonnés pour une chaîne séparée par des espaces. Continuez à utiliser des tableaux.

  1. Toujours citer l'extension d'un tableau indexé @; sinon, il n'y a aucune raison d'utiliser @ sur *.
  2. En règle générale, évitez les noms de variables toutes majuscules; ils sont (pour la plupart) réservés à l'usage du shell.
  3. Entourez les filtres joints par -o dans les parenthèses échappées afin que find les traite comme une seule condition à remplir en plus du primaire -type.
  4. Utilisez -exec ... + pour que chmod puisse fonctionner sur plusieurs fichiers par appel, plutôt que de l'appeler une fois pour chaque fichier séparément.

#!/bin/bash 
file_extensions=(txt png jpg) 

first=1 
for ext in "${file_extensions[@]}" 
do 
# echo "$ext" 
    if [[ $first == 1 ]] 
    then 
     find_filter=(-iname "*.$ext") 
     first=0 
    else 
     find_filter+=(-o -iname "*.$ext") 
    fi 
done 


# Read and write only for user and group, ignore case '-iname' 
find . -type f \("${find_filter[@]}" \) -exec chmod 660 + 
+0

@Benoit Merci d'avoir nettoyé ma réponse écrite à la hâte. – chepner

+0

Merci @chepner - qui a sauvé ma journée. Je connais maintenant mieux comment utiliser les tableaux et le plus important à propos de la syntaxe find avec() et la nécessité de les citer! – JDB

0

OK, je trouve la raison pour laquelle il ne fonctionne pas

$ find . $FIND_ARGS &  # Does not work 
[1] 6312  
$ cat /proc/6312/cmdline 
find . -iname '*.png' 

$ find . -iname '*.png' & # Works 
[1] 8901 
$ cat /proc/8901/cmdline 
find . -iname *.png 

Ainsi, les citations lors de l'appel de la commande directement ne sont là que pour bash de ne pas étendre les arguments. Lorsque vous lancez la commande indirectement, vous devez supprimer ces guillemets.

+0

Merci Benoit, je confirme que cela fonctionne pour le cas simple (même si je ne comprends pas pourquoi). Mais aussi bien que j'essaie d'utiliser la resut comme argument pour '-exec chmod 660 {} \;' il échoue avec: Trouver le filtre: -iname filter.txt -o -iname z.png -o -iname * .jpg find: prédicat inconnu '-iname * .txt -o -iname * .png -o -iname * .jpg ' – JDB