¿Cómo encontrar dos archivos con datos coincidentes en un script de shell y un almacén de datos duplicado en otro archivo en shell?
#!/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
Escribí código pero no funcionó. ¿Cómo escribirlo?
Comentarios
Responder
Para probar si dos los archivos son iguales, use 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
El -s
marca a cmp
hará que la utilidad sea «silenciosa». El estado de salida de cmp
será cero al comparar dos archivos que son idénticos. Esto se usa en el código anterior para imprimir un mensaje sobre si los dos archivos son idénticos o no.
Si sus dos archivos de entrada contienen una lista de rutas de archivos que desea comparar, luego use un ciclo doble como este:
Aquí, el resultado se produce tanto en el terminal como en el archivo file-comparison.out
.
Se supone que ningún nombre de ruta en los dos archivos de entrada contiene líneas nuevas incrustadas.
El código primero lee todos los nombres de ruta de uno de los archivos en una matriz, files1
, usando mapfile
. Hago esto para evitar tener que leer ese archivo más de una vez, ya que tendremos que revisar todos esos nombres de ruta para cada nombre de ruta en el otro archivo. Notarás que en lugar de leer de $filelist1
en el ciclo interno, simplemente repito los nombres en la matriz files1
.
Comentarios
- Necesito un programa total en bash shell
- @santhoshreddy Ver la respuesta actualizada.
Respuesta
La forma más sencilla es usar el comando diff
.
ejemplo:
Supongamos que el primer archivo es file1.txt
y contiene:
I need to buy apples. I need to run the laundry. I need to wash the dog. I need to get the car detailed.`
y el segundo archivo 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.
entonces podemos usar diff para mostrarnos automáticamente qué líneas difieren entre los dos archivos con este comando:
diff file1.txt file2.txt
y la salida será:
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.
Echemos un vistazo a lo que significa esta salida. Lo importante a recordar es que cuando diff le describe estas diferencias, lo hace en un contexto prescriptivo: le dice cómo cambiar el primer archivo para que coincida con el segundo archivo. La primera línea de la salida de diferencias contendrá:
- los números de línea correspondientes al primer archivo,
- una letra (a para agregar, c para cambiar o d para eliminar )
- números de línea correspondientes al segundo archivo.
En nuestro resultado anterior, «2,4c2,4 « significa:» Líneas 2 a 4 en el primer archivo deben cambiarse para que coincidan con las líneas 2 hasta 4 en el segundo archivo. » Luego nos dice cuáles son esas líneas en cada archivo:
- Las líneas precedidas por un < son líneas del primer archivo;
- líneas precedidas por> son líneas del segundo archivo.
- Los tres guiones («—«) simplemente separan las líneas del archivo 1 y el archivo 2.
Respuesta
Aquí hay una script de shell bash para comparar archivos:
#!/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
produciendo:
$ ./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.
Los comentarios sobre Se pueden eliminar comandos específicos para salir a la primera diferencia que se ve, y si desea ver cada línea que se lee.
Consulte la página en http://www.linuxjournal.com/content/reading-multiple-files-bash para obtener detalles sobre descriptores de archivos como «& 3».
Mis mejores deseos … saludos, drl
Comentarios
-
head
es una utilidad externa, y lo que es$HOME/bin/context
? ¿Y qué significan los comentarios en la parte superior? - Head muestra la entrada. No juega aparte en la diferenciación. Como ocurre con otros elementos, » context » es local para mostrar el contexto del entorno. Al incluir eso, no ‘ no tenemos que discutir si las versiones de los sistemas operativos y las utilidades difieren.
- Faltaba una exportación, gracias por notarlo.
- Todavía no ‘ entiendo el comentario.¿Qué ‘ es un » usuario externo » y por qué desearía establecer el ruta para un script que es puro
bash
? - Escribimos código para nuestra tienda, por lo que la configuración de la ruta puede diferir para usuarios externos. Agregamos que si parece necesario omitir nuestra configuración. Esta es una plantilla que se modifica para mostrar la información sobre el entorno en el que se ejecutó el código. Si se transformara en un código de producción, digamos para los clientes, en lugar de un código de demostración, ‘ querríamos estar seguros de que no se utiliza ninguna de nuestras rutas locales. for context está diseñado para que si ese archivo no se encuentra no ocurrirá nada, ni siquiera un error, pero no se enumerarán versiones.
diff
comando?