Comment enregistrer la sortie d'une commande (par exemple diff) dans une variable

21

Je veux tester s'il y a une sortie de diff(tester si les fichiers sont les mêmes), si aucun echo "Passed $x" else echo "Failed $x". Je suis venu avec une étape intermédiaire (enregistrer la sortie de diff dans un fichier puis lire à partir du fichier)

diff "./helloworld$x.out" "./output/helloworld$x.out" > tmp.txt;
output="`cat tmp.txt`";

if [ "$output" = "" ];
  then
    echo "Passed $x";
  else
    echo "Failed $x";
  fi;

Je suis sûr que le code peut être amélioré? La question principale est: est-il possible de sauvegarder la sortie de diffdirectement dans une variable?

Jiew Meng
la source

Réponses:

18

Cela marche:

if diff "./helloworld$x.out" "./output/helloworld$x.out"> / dev / null; puis
    echo "Passed $ x";
autre
    echo "Echec $ x";
Fi

Si vous utilisez une variable au lieu de echo vous pouvez supprimer la elsebranche: définissez la variable sur false avant le ifet enregistrez 2 lignes de code.

Si vous voulez réellement mettre le résultat dans une utilisation variable:

some_var="$(diff "./helloworld$x.out" "./output/helloworld$x.out")"

Y compris mon test pour voir si cela fonctionne réellement:

rinzwind @ discworld: ~ $ touch 1
rinzwind @ discworld: ~ $ touch 2
rinzwind @ discworld: ~ $ plus de test
si diff 1 2> / dev / null; puis
    echo "Passed $ x";
autre
    echo "Echec $ x";
Fi
rinzwind @ discworld: ~ $ ./test
Réussi 

rinzwind @ discworld: ~ $ vi 2
rinzwind @ discworld: ~ $ plus 2
2
rinzwind @ discworld: ~ $ ./test
Échoué 

Sur la >/dev/nullpartie: >/dev/null 2>&1enverra la sortie vers >/dev/nullet 2>&1 enverra les erreurs standard dans le même fichier ( &1signifie 'utiliser le premier paramètre') devant cette commande (donc elle utilise également /dev/null).

sidenote: sdiffaffichera une liste côte à côte diff:

sdiff 1 2 
1 1
2 2
3 3
4 4
5 5
7 7
                                  > 8
9 9
10 10
Rinzwind
la source
Merci ça marche, mais je ne comprends pas ce qui se ... > /dev/nullpasse dans ce contexte. La sortie de diff sera goto / dev / null mais n'est-ce pas rien?
Jiew Meng
1
Le diff affichera toutes les différences entre les fichiers sur votre écran et> / dev / null s'assurera que la sortie de la commande est redirigée vers l'oubli. L'if est toujours exécuté en fonction de la sortie.
Rinzwind
1
L'instruction if vérifie le code de sortie de la commande diff. 0 signifie qu'aucune différence n'a été trouvée, tandis que 1 signifie qu'il y avait une ou plusieurs différences.
Knut Eldhuset
17

diff peut même supprimer complètement la sortie à l'exception du message "Files / bin / bash et / bin / sh differ" en utilisant le code ci-dessous.

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"

if diff -q "$file1" "$file2"; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Si vous souhaitez même masquer ce message, vous devez ajouter > /dev/nullaprès la commande diff pour masquer la sortie de diff:

if diff -q "$file1" "$file2" >/dev/null; then

/dev/null est un fichier spécial qui agit comme un trou noir, si vous y écrivez, il disparaîtra, si vous le lisez, vous ne récupérerez rien.

Notez que bash n'a pas besoin ;de terminer les lignes.

Quant à la question d'origine, pour enregistrer la sortie d'un programme dans une variable:

file1="./helloworld$x.out"
file2="./output/helloworld$x.out"
output="$(diff -q "$file1" "$file2")"

# the quotes are mandatory, this checks whether $output is empty or not
if [ -n "$output" ]; then
    echo "Passed $x"
else
    echo "Failed $x"
fi

Autres moyens de vérifier si une variable est vide:

[ "$output" = "" ]
[ "$output" == "" ]
[[ "$output" == "" ]]
[[ $output == "" ]]

Si vous utilisez Bash, les deux dernières commandes sont recommandées pour la comparaison de chaînes. Sinon, le premier et [ -n "$output" ]est recommandé.

Lekensteyn
la source
6

a) La sortie de command1 peut être capturée avec

output=$(diff "helloworld$x.out" "output/helloworld$x.out") 

ou avec des crochets, mais ceux-ci sont déconseillés, car vous ne pouvez pas les imbriquer, et ils peuvent être difficiles à distinguer des apostrophes, selon la police:

 output=`cmd1`

b) Au lieu d'écrire dans un fichier, puis de lire ce fichier (ou de saisir la sortie, puis de l'écho), vous utiliseriez directement un tuyau:

 cmd1 > file
 cat file | cmd2 

 output=$(cmd1)
 echo "${output}" | cmd2 

=>

 cmd1 | cmd2 

mais dans votre exemple, vous n'êtes pas intéressé par le résultat, mais par le résultat du programme - cela at-il fonctionné?

 diff "helloworld$x.out" "output/helloworld$x.out" && echo "success" || echo "failure" 

Pour en savoir plus sur l'utilisation de && et || recherchez "raccourci ET et raccourci OU".

Pour garder la sortie propre, vous pouvez rediriger la sortie de 'diff' vers nulle part:

 diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null && echo "success" || echo "failure" 

Pour saisir le succès et l'évaluer plus tard, vous stockez le résultat de la dernière commande dans une variable avec $ ?:

diff "helloworld$x.out" "output/helloworld$x.out" >/dev/null
result=$?
# do something else
case $result in 
   0) echo success ;;
   *) echo failure ;;
esac
Utilisateur inconnu
la source
3

Si vous voulez savoir si deux fichiers sont identiques ou différents (mais ne vous souciez pas de la différence), cmpc'est plus approprié.

if cmp -s file1 file2; then echo "Equal"; else echo "Not equal"; fi
geirha
la source