Parcourez les fichiers en excluant les répertoires

11

J'ai besoin que mon script fasse quelque chose pour chaque fichier du répertoire courant à l'exclusion de tout sous-répertoire.

Par exemple, dans le chemin actuel, il y a 5 fichiers, mais 1 d'entre eux est un dossier (un sous-répertoire). Mon script doit activer une commande donnée comme arguments lors de l'exécution dudit script. C'est-à-dire que "bash script wc -w" devrait donner le nombre de mots de chaque fichier dans le répertoire en cours, mais aucun des dossiers, afin que la sortie ne contienne jamais aucune des lignes "/ sub / dir: Is a directory".

Mon script actuel:

#!/bin/bash
dir=`pwd`
for file in $dir/*
do
    $* $file
done

J'ai juste besoin d'exclure les répertoires de la boucle, mais je ne sais pas comment.

Tõnis Piip
la source

Réponses:

11
#!/bin/bash -

for file in "$dir"/*
do
  if [ ! -d "$file" ]; then
      "$@" "$file"
  fi
done

Notez qu'il exclut également les fichiers qui sont de type lien symbolique et où le lien symbolique se résout en un fichier de type répertoire (qui est probablement ce que vous voulez).

Alternative (à partir des commentaires), vérifiez uniquement les fichiers:

for file in "$dir"/*
do
  if [ -f "$file" ]; then
      "$@" "$file"
  fi
done
laktak
la source
@roaima bonne idée!
laktak
2
Mieux vaut utiliser if [ -f "$file" ]; then .... Pas un répertoire ne retournerait non seulement des fichiers normaux mais aussi des sockets et des liens symboliques.
JRFerguson
@JRFerguson basé sur la question de l'OP, je dirais que l'inclusion de prises et de tuyaux serait une très mauvaise idée. Quant aux liens symboliques, ils sont implicitement inclus avec ! -ddéjà.
roaima
J'ai utilisé [-f $ file] dans mon script final. Notez l'absence de guillemets dans la condition if. Presque partout où je regardais, il y avait des guillemets autour de $ file, mais je devais les supprimer pour que mon script fonctionne.
Tõnis Piip
3

Voici une alternative à l'utilisation d'une boucle for si ce que vous devez faire est simple (et n'implique pas de définir des variables dans le shell principal & c).

Vous pouvez utiliser findavec -execet utiliser -maxdepth 1pour éviter de revenir dans le sous-répertoire.

[ -n "$1" ] && find "$dir" -type f -mindepth 1 -maxdepth 1 -exec "$@" "{}" \;

Le [ -n "$1" ]est là pour éviter d'exécuter tous les fichiers du répertoire lorsque le script ne reçoit aucun argument.

Gregory Nisbet
la source
2

Dans zsh, vous pouvez utiliser des qualificatifs glob pour restreindre les correspondances génériques par type de fichier. Par exemple, l'ajout (.)après le modèle le restreint aux fichiers normaux.

wc -w *(.)

Pour gérer les noms de fichiers commençant par -ou ., utilisez wc -c -- *(.N)ou wc -c ./*(.N). Si vous souhaitez également inclure des liens symboliques vers des fichiers standard, faites-le *(-.).

Les autres shells courants n'ont pas une telle fonctionnalité, vous devez donc utiliser un mécanisme différent pour filtrer par fichier, comme tester les types de fichiers dans une boucle ou find.

Gilles 'SO- arrête d'être méchant'
la source
0

Bash for loop excluant les sous-répertoires ('/') et les liens (@):

for f in `ls|egrep -v '/|@'`; do echo $f; done
James Armstrong
la source