J'ai une liste de fichiers que je veux vérifier s'ils existent sur mon système de fichiers. J'ai pensé à faire cela en utilisant find
comme dans:
for f in $(cat file_list); do
find . -name $f > /dev/null || print $f
done
(en utilisant zsh
) mais cela ne fonctionne pas, car il find
semble se terminer, 0
qu'il trouve ou non le fichier. Je suppose que je pourrais le passer à travers un autre test qui teste pour voir si find
produit une sortie (brute mais efficace serait de remplacer la > /dev/null
avec |grep ''
) mais cela ressemble à l'utilisation d'un troll pour attraper une chèvre (d'autres nationalités pourraient dire quelque chose à propos des marteaux et des noix ).
Existe-t-il un moyen de contraindre find
à me donner une valeur de sortie utile? Ou au moins pour obtenir une liste de ces fichiers qui n'ont pas été trouvés? (Je peux imaginer que ce dernier soit peut-être plus facile grâce à un choix astucieux de connecteurs logiques, mais il semble que je sois toujours lié par des nœuds lorsque j'essaie de le comprendre.)
Contexte / Motivation: J'ai une sauvegarde "maître" et je veux vérifier que certains fichiers sur ma machine locale existent sur ma sauvegarde maître avant de les supprimer (pour créer un peu d'espace). J'ai donc fait une liste des fichiers, ssh
les ai édités sur la machine principale, et j'étais alors à court de trouver le meilleur moyen de trouver les fichiers manquants.
locate
.locate
pas l'état actuel du système de fichiers, il peut s'agir d'un jour, voire d'une semaine. Cela convient comme base pour tester les sauvegardes.Réponses:
find
considère que rien ne constitue un cas particulier de réussite (aucune erreur n'est survenue). Une façon générale de tester si les fichiers correspondent à certainsfind
critères est de tester si la sortie defind
est vide. Pour une meilleure efficacité lorsqu'il y a des fichiers correspondants, utilisez-quit
sur GNU find pour le faire quitter à la première correspondance, ouhead
(head -c 1
si disponible, sinonhead -n 1
ce qui est standard) sur d'autres systèmes pour le faire mourir d'un tuyau cassé plutôt que de produire une sortie longue.En bash ≥4 ou zsh, vous n'avez pas besoin de la
find
commande externe pour une simple correspondance de nom: vous pouvez utiliser**/$name
. Version basique:Version Zsh sur un principe similaire:
Ou voici un moyen plus court mais plus cryptique de tester l'existence d'un fichier correspondant à un modèle. Le qualificatif glob
N
rend la sortie vide s'il n'y a pas de correspondance,[1]
ne conserve que la première correspondance ete:REPLY=true:
modifie chaque correspondance pour qu'elle se développe au1
lieu du nom de fichier correspondant.**/"$name"(Ne:REPLY=true:[1]) false
S'étend donc entrue false
cas de correspondance, ou simplementfalse
s'il n'y a pas de correspondance.Il serait plus efficace de combiner tous vos noms en une seule recherche. Si le nombre de modèles n'est pas trop important pour la limite de longueur de votre système sur une ligne de commande, vous pouvez joindre tous les noms avec
-o
, effectuer un seulfind
appel et post-traiter la sortie. Si aucun des noms ne contient de métacaractères shell (afin que les noms soient également desfind
modèles), voici un moyen de post-traiter avec awk (non testé):Une autre approche consisterait à utiliser Perl et
File::Find
, ce qui facilite l'exécution du code Perl pour tous les fichiers d'un répertoire.Une autre approche consiste à générer une liste de noms de fichiers des deux côtés et à travailler sur une comparaison de texte. Version Zsh:
la source
zsh
solution avec la**
syntaxe. C'est une solution très simple et même si elle n'est peut-être pas la plus efficace en termes de machine , elle est probablement la plus efficace si je m'en souviens! De plus, la première solution ici répond à la question réelle en ce qu'elle sefind
transforme en quelque chose où le code de sortie distingue "J'ai obtenu une correspondance" de "Je n'ai pas obtenu de correspondance".Vous pouvez utiliserstat
pour déterminer si un fichier existe sur le système de fichiers.Vous devez utiliser les fonctions intégrées du shell pour tester si des fichiers existent.
Le "test" est facultatif et le script fonctionnera réellement sans lui, mais je l'ai laissé là pour la lisibilité.
Edit: Si vous n'avez vraiment pas d'autre option que de travailler pour une liste de noms de fichiers sans chemins, je vous suggère de créer une liste de fichiers une fois avec find, puis de l'itérer avec grep pour déterminer quels fichiers sont là.
Notez que:
la source
Une première approche simpliste pourrait être:
a) triez votre liste de fichiers:
pour trouver des disparus, ou
pour trouver des correspondances
Désavantages:
find pourrait rechercher plusieurs fichiers à la fois, avec une certaine préparation:
find -name a.file -or -name -b.file -or -name c.file ...
La localisation pourrait-elle être une option? Encore une fois, une liste présélectionnée de fichiers supposait:
Une recherche de foo.bar ne correspondra pas à un fichier foo.ba ou oo.bar avec la construction --regexp-(à ne pas confondre avec regex sans p).
Vous pouvez spécifier une base de données spécifique pour la localisation, et vous devez la mettre à jour avant la recherche, si vous avez besoin des résultats les plus récents.
la source
Je pense que cela peut aussi être utile.
Il s'agit d'une solution sur une seule ligne, au cas où vous opteriez pour que votre "liste" soit de vrais fichiers que vous souhaitez synchroniser avec un autre dossier:
pour aider à la lecture:
cet exemple exclut les fichiers de sauvegarde "* ~" et limite le type de fichier normal "-type f"
la source
Peut être?
la source
Pourquoi ne pas simplement comparer la longueur de la liste de requêtes avec la longueur de la liste de résultats?
la source