Comment différencier plusieurs fichiers d'un répertoire à l'autre?

19

J'essaie de trouver des diffs entre tous les fichiers de mêmes noms sur deux copies d'un répertoire (disons un travail et une sauvegarde). Par exemple, je peux diffdeux fichiers du même nom dans les deux:

> diff d1/f.cpp d2/f.cpp

ou je peux trouver des différences entre les répertoires:

> diff d1 d2

mais comment puis-je trouver des différences entre les *.cppfichiers uniquement?

> diff d1/*.cpp d2/*.cpp

ne semble pas fonctionner (pour des raisons évidentes).

[Il est probablement facile à résoudre avec des boucles, mais j'essaie de trouver un moyen plus élégant]

ysap
la source

Réponses:

13

Vous pouvez utiliser une boucle shell qui exécute diff pour chaque fichier, bien que cela n'attrape pas les cas où d2 contient un fichier, mais pas d1. Cela pourrait cependant suffire.

for file in d1/*.cpp; do
    diff "$file" "d2/${file##*/}"
done

Ou tout sur une seule ligne:

for file in d1/*.cpp; do diff "$file" "d2/${file##*/}"; done

La ${file##*/}pièce est une extension de paramètre spéciale.

Si la variable de fichier contient d1/hello.cpp, alors "${file##*/}"se développera jusqu'à hello.cpp(la valeur du fichier, mais avec tout ce qui va jusqu'à, et y compris, le dernier / supprimé).

Ainsi "d2/${file##*/}"résultera d2/hello.cppet la commande diff résultante est doncdiff d1/hello.cpp d2/hello.cpp

Voir http://mywiki.wooledge.org/BashFAQ/100 pour plus d'informations sur les manipulations de chaînes dans bash.

Par ailleurs, un système de contrôle de version (tel que subversion, git, mercurial etc ...) rendrait ce type de diff beaucoup plus facile.

geirha
la source
Je pense que des deux excellentes réponses, celle-ci est plus simple lorsqu'il y a plusieurs types de fichiers (bien que j'aie mentionné dans la question que je cherche une solution sans boucles), donc je l'ai acceptée. Le seul ajout ajouté est echo "${file##*/}";avant la diffcommande, donc on sait quels fichiers sont réellement comparés. De plus, comme mentionné dans la réponse de @ Rinzwind, cette méthode ne couvre pas le cas où la liste des fichiers n'est pas exactement la même dans les deux répertoires.
2012
52

diff -qr {DIR1} {DIR2} fait tous les fichiers dans les deux répertoires.

  • q ne montre que des différences
  • rfait récursif. Laissez-le de côté si vous n'en avez pas besoin

Vous ne pouvez pas dire diffdirectement d'utiliser des caractères génériques, mais vous pouvez ajouter:

-x PAT  --exclude=PAT
    Exclude files that match PAT.

-X FILE    --exclude-from=FILE
   Exclude files that match any pattern in FILE.

pour exclure des fichiers. Donc, si vous voulez seulement que *.cppla méthode la plus simple soit de créer un fichier texte qui répertorie tous les fichiers qui ne le sont pas *.cpp. Vous pouvez le faire avec la commande suivante: ls -I "*.cpp" > excluded_filesoù l' -I "*.cpp"argument ignore tous les fichiers .cpp. Notez que les guillemets sont nécessaires.

Rinzwind
la source
Simple et fonctionne parfaitement.
Jose Gómez
4

Quelque temps après avoir posé la question, j'ai découvert l' meldutilitaire diff et je l'utilise depuis. Il s'agit d'un excellent programme basé sur une interface graphique qui rend la comparaison et la fusion entre les fichiers et le répertoire une tâche très facile. Il effectue des comparaisons à deux ou trois voies.

Plus précisément, il répond à ma question d'origine en ce qu'il vous montre une comparaison codée par couleur du contenu du répertoire et vous permet de comparer des fichiers spécifiques en double-cliquant sur le nom du fichier.

Si l'on a besoin de plus d'une comparaison à trois, alors gvimdiff(basé sur l' viméditeur) est aussi un excellent qui fournit cette fonctionnalité.

ysap
la source
1

Il existe une solution légère pour cela:

  1. Configurez ce minuscule plugin http://www.vim.org/scripts/script.php?script_id=5309
  2. Faire diff dir1 dir2 | vim -R -à la coquille

Il ajoutera des plis et une comparaison côte à côte pour les fichiers modifiés.

Yuriy Ershov
la source