Compte tenu du script ci-dessous, je voudrais éviter l'exécution du pipeline si un fichier n'existe pas.
Comment puis-je quitter le script immédiatement si le fichier txt n'est pas trouvé?
ls */*.txt | grep ab1 | awk '{print $1, $1}' | sed "s/\"/\"\"/g" | xargs -L1 mv
Vous pouvez vérifier l'existence d'un fichier avec quelque chose comme:
if [[ -f x.txt ]] ; then
echo file exists.
fi
Pour quitter s'il ne le fait pas quelque chose comme ça suffirait:
if [[ ! -f x.txt ]] ; then
echo 'File "x.txt" is not there, aborting.'
exit
fi
Le -f <file>
n'est que n parmi les nombreuses expressions conditionnelles que vous pouvez utiliser. Si vous consultez la page de manuel bash
sous CONDITIONAL EXPRESSIONS
, vous en verrez une multitude.
Si (comme indiqué dans une mise à jour de question) vous souhaitez vérifier si un caractère générique aboutit à des fichiers, vous pouvez simplement le développer, en supprimant les erreurs. S'il n'y en a pas, vous vous retrouverez avec une chaîne vide qui peut être détectée avec -z
:
if [[ -z "$(ls -1 */*.txt 2>/dev/null | grep ab1)" ]] ; then
echo 'There are no "*/*.txt" files.'
exit
fi
Notez que j'ai utilisé -1
pour forcer un fichier par ligne même si Linux ls
le fait par défaut si le périphérique de sortie n'est pas un terminal (à partir de la mémoire). C'est juste au cas où vous essayez ceci sur une machine qui pas force un par ligne dans ce cas.
Gardez cependant à l'esprit que si vous avez des espaces dans vos noms de fichiers, utiliser ls
puis awk
pour extraire la colonne 1 ne fonctionnera pas trop bien. Par exemple, le fichier abc ab1.txt
entraînera l'extraction uniquement du bit abc
.
Utilisation de find
avec -print0
, combiné avec xargs
avec -0
est la manière habituelle de traiter correctement les fichiers qui peuvent contenir des caractères "spéciaux". Il existe de nombreuses autres options que vous pouvez donner à find
pour vous assurer que seuls les fichiers requis sont traités, tels que -maxdepth
pour limiter la distance parcourue dans l'arborescence et -name
pour filtrer correctement les noms de fichiers.
Cependant, si vous savez que vous n'aurez jamais ces types de fichiers, il est probablement correct d'utiliser la solution ls
, assurez-vous simplement que vous êtes à l'aise avec ses défauts.
test
Un moyen rapide et court de tester l'existence:
test -e $FILENAME || exit
Vous pouvez l'enchaîner en faisant:
test -e $FILENAME && something | something-else
Dans ce cas, something
et something-else
ne s'exécutera que si le fichier existe.
Par exemple:
➤ test -e ~/.bashrc && echo True || echo False
True
➤ test -e ./exists-not && echo True || echo False
False
Mis à part: Notez que [
est un alias pour test
. La sémantique de [[
sont définis par bash et peuvent être trouvés sur la page de manuel bash
... vous feriez probablement mieux d'utiliser find
pour récupérer vos fichiers:
find ./ -maxdepth 2 -name "*ab1*.txt" -exec do-something-to-filename '{}' \;
Comme la sortie de ls
ne peut pas être analysée de manière fiable. Cela n'exécutera également que la commande do-something-to-filename
si le nom de fichier existe, c'est ce que je pense que vous essayez de faire.
{}
sera remplacé par le nom de fichier pour chaque invocation de do-something-to-filename
.
J'ai essayé ça et ça a marché pour moi
test -s <<your file path>> && exit 0 || <<things to do when file NOT exists>>
Notez que je quitte réellement lorsque le fichier n'est pas présent
find ... -exec ...
ou find ... -print0 | xargs -0 ...
est généralement bien, mais vous pouvez le faire directement avec un glob en utilisant l'option nullglob
de bash:
bash-3.2$ echo *foo
*foo
bash-3.2$ shopt -s nullglob
bash-3.2$ echo *foo
bash-3.2$
Selon le reste de votre script, vous pouvez ou non vouloir réinitialiser cela avec shopt -u nullglob
.