Jak znaleźć dwa pliki zgodne z danymi w skrypcie powłoki i zduplikowaną składnicę danych w innym pliku w powłoce?
#!/bin/bash file1="/home/vekomy/santhosh/bigfiles.txt" file2="/home/vekomy/santhosh/bigfile2.txt" while read -r $file1; do while read -r $file2 ;do if [$file1==$file2] ; then echo "two files are same" else echo "two files content different" fi done done
Napisałem kod, ale nie zadziałał. Jak go napisać?
Komentarze
Odpowiedź
Aby tylko sprawdzić, czy dwa pliki są takie same, użyj cmp -s
:
#!/bin/bash file1="/home/vekomy/santhosh/bigfiles.txt" file2="/home/vekomy/santhosh/bigfile2.txt" if cmp -s "$file1" "$file2"; then printf "The file "%s" is the same as "%s"\n" "$file1" "$file2" else printf "The file "%s" is different from "%s"\n" "$file1" "$file2" fi
-s
oznaczenie cmp
spowoduje wyciszenie narzędzia. Status wyjścia cmp
będzie wynosił zero podczas porównywania dwóch identycznych plików. Jest to używane w powyższym kodzie do wydrukowania komunikatu o tym, czy oba pliki są identyczne, czy nie.
Jeśli twoje dwa pliki wejściowe zawierają listę ścieżek plików który chcesz porównać, a następnie użyj podwójnej pętli w ten sposób:
Tutaj wynik jest tworzony zarówno na terminalu, jak iw pliku file-comparison.out
.
Zakłada się, że żadna ścieżka w dwóch plikach wejściowych nie zawiera osadzonych znaków nowej linii.
Kod najpierw wczytuje wszystkie ścieżki z jednego z plików do tablicy, files1
, używając mapfile
. Robię to, aby uniknąć konieczności wielokrotnego czytania tego pliku, ponieważ będziemy musieli przejść przez wszystkie te ścieżki dla każdej ścieżki w innym pliku. Zauważysz, że zamiast czytać z $filelist1
w wewnętrznej pętli, po prostu iteruję po nazwach w tablicy files1
.
Komentarze
- Potrzebuję całkowitego progamu w powłoce basha
- @santhoshreddy Zobacz zaktualizowaną odpowiedź.
Odpowiedź
Najłatwiej jest użyć polecenia diff
.
przykład:
załóżmy, że pierwszy plik to file1.txt
i zawiera:
I need to buy apples. I need to run the laundry. I need to wash the dog. I need to get the car detailed.`
, a drugi plik file2.txt
I need to buy apples. I need to do the laundry. I need to wash the car. I need to get the dog detailed.
następnie możemy użyć diff, aby automatycznie wyświetlić nam, które linie różnią się między dwoma plikami za pomocą tego polecenia:
diff file1.txt file2.txt
a wynik będzie wyglądał następująco:
2,4c2,4 < I need to run the laundry. < I need to wash the dog. < I need to get the car detailed. --- > I need to do the laundry > I need to wash the car. > I need to get the dog detailed.
Przyjrzyjmy się, co oznacza to wyjście. Ważną rzeczą do zapamiętania jest to, że kiedy diff opisuje ci te różnice, robi to w kontekście nakazowym: mówi ci, jak zmienić pierwszy plik, aby pasował do drugiego. Pierwsza linia wyniku diff będzie zawierać:
- numery wierszy odpowiadające pierwszemu plikowi,
- literę (a jak dodawanie, c jak zmiana lub d jak usuwanie )
- numery wierszy odpowiadające drugiemu plikowi.
W powyższym wyniku „2,4c2,4 „ oznacza:„ Linie 2 do 4 w pierwszym pliku należy zmienić, aby dopasować wiersze 2 do 4 w drugim pliku. ” Następnie informuje nas, jakie linie znajdują się w każdym pliku:
- Linie poprzedzone znakiem < to linie z pierwszego pliku;
- linie poprzedzone znakiem> to linie z drugiego pliku.
- Trzy myślniki („—”) tylko oddzielają wiersze pliku 1 i pliku 2.
Odpowiedź
Oto czysta skrypt powłoki bash do porównywania plików:
#!/usr/bin/env bash # @(#) s1 Demonstrate rudimentary diff using shell only. # Infrastructure details, environment, debug commands for forum posts. # Uncomment export command to run as external user: not context, pass-fail. # export PATH="/usr/local/bin:/usr/bin:/bin" set +o nounset LC_ALL=C ; LANG=C ; export LC_ALL LANG pe() { for _i;do printf "%s" "$_i";done; printf "\n"; } pl() { pe;pe "-----" ;pe "$*"; } db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; } db() { : ; } C=$HOME/bin/context && [ -f "$C" ] && $C set -o nounset FILE1=${1-data1} shift FILE2=${1-data2} # Display samples of data files. pl " Data files:" head "$FILE1" "$FILE2" # Set file descriptors. exec 3<"$FILE1" exec 4<"$FILE2" # Code based on: # http://www.linuxjournal.com/content/reading-multiple-files-bash # Section 2, solution. pl " Results:" eof1=0 eof2=0 count1=0 count2=0 while [[ $eof1 -eq 0 || $eof2 -eq 0 ]] do if read a <&3; then let count1++ # printf "%s, line %d: %s\n" $FILE1 $count1 "$a" else eof1=1 fi if read b <&4; then let count2++ # printf "%s, line %d: %s\n" $FILE2 $count2 "$b" else eof2=1 fi if [ "$a" != "$b" ] then echo " File $FILE1 and $FILE2 differ at lines $count1, $count2:" pe "$a" pe "$b" # exit 1 fi done exit 0
tworzenie:
$ ./s1 Environment: LC_ALL = C, LANG = C (Versions displayed with local utility "version") OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64 Distribution : Debian 8.9 (jessie) bash GNU bash 4.3.30 ----- Data files: ==> data1 <== I need to buy apples. I need to run the laundry. I need to wash the dog. I need to get the car detailed. ==> data2 <== I need to buy apples. I need to do the laundry. I need to wash the car. I need to get the dog detailed. ----- Results: File data1 and data2 differ at lines 2, 2: I need to run the laundry. I need to do the laundry. File data1 and data2 differ at lines 3, 3: I need to wash the dog. I need to wash the car. File data1 and data2 differ at lines 4, 4: I need to get the car detailed. I need to get the dog detailed.
Komentarze na określone polecenia mogą zostać usunięte, aby wyjść przy pierwszej zauważonej różnicy i jeśli chcesz zobaczyć każdy czytany wiersz.
Zobacz stronę pod adresem http://www.linuxjournal.com/content/reading-multiple-files-bash , aby uzyskać szczegółowe informacje na temat deskryptorów plików, takich jak „& 3″.
Pozdrawiam … Pozdrawiam, drl
Komentarze
-
head
to zewnętrzne narzędzie, a czym jest$HOME/bin/context
? A co znaczą komentarze u góry? - Głowa wyświetla dane wejściowe. W różnicowaniu nie gra osobno. Podobnie jak w przypadku niektórych innych elementów, ” kontekst ” jest lokalny, aby pokazać kontekst środowiska. Uwzględniając to, nie ' nie musimy dyskutować, czy wersje systemów operacyjnych i zastosowań różnią się.
- Brakuje eksportu, dziękujemy za zauważenie.
- Nadal nie ' nie rozumiem komentarza.Co ' jest ” użytkownikiem zewnętrznym ” i dlaczego miałbyś chcieć ustawić ścieżka do skryptu, który jest czysty
bash
? - Piszemy kod dla naszego sklepu, więc ustawienia ścieżki mogą się różnić dla użytkowników zewnętrznych. Dodajemy, że jeśli okaże się konieczne pominięcie naszych ustawień. Jest to szablon zmodyfikowany w celu wyświetlenia informacji o środowisku, w którym został wykonany kod. Gdyby został przekształcony w kod produkcyjny, powiedzmy dla klientów, zamiast kodu demonstracyjnego, ' d chcemy mieć pewność, że żadna z naszych ścieżek lokalnych nie jest używana. for context jest zaprojektowany w taki sposób, że jeśli ten plik nie zostanie znaleziony, nic się nie stanie, nawet błąd, ale żadne wersje nie zostaną wymienione.
diff
polecenie?