Actualmente estoy escribiendo el siguiente guión. El código busca en un directorio determinado un nombre de archivo ingresado por el usuario. El script primero verifica si el archivo de entrada es un gzip; de ser así, ejecuta las comprobaciones correspondientes. Si el archivo no está comprimido con gzip, responde con un texto de archivo incompatible.
El problema con el que me encuentro está en línea 7
. No importa la extensión del archivo, recibo un archivo incompatible como resultado final.
#!/bin/bash
DATE=$(date +%Y-%m-%d)
L0_Report_Generator=("/home/ubuntu/$gzip_file")
echo -n "Enter File Directory:"$gzip_file
read $gzip_file
for gzip_file in {$L0_Report_Generator}; do
if [[ $gzip_file = "test_sub"*"gz" ]] #Check file extension for gzip compression
then
gunzip $gzip_file
echo "file Level 0 QC Check"
echo ${DATE}
echo "File Header"
cat $gzip_file | head
echo "Total Records"
cat $gzip_file | wc -l
echo "File Unique Records Size"
cat $L0_Report_Generator | sort -u | wc -l
rm $gzip_file
else [[ $gzip_file != "test_sub"*"gz" ]] #If file is anything other than .gz and csv - rort will not run
then
echo "incompatible file"
fi
done
Respuesta1
Si desea verificar si hay una extensión de nombre de archivo ".gz" usando una expresión comodín dentro de una declaración if, entonces usaría una expresión como la siguiente:
if [[ "${gzip_file}" = *.gz ]]; then echo true; else echo false; fi
Así es como puedes probarlo:
if [[ "file.gz" = *.gz ]]; then echo true; else echo false; fi
y:
if [[ "file.txt" = *.gz ]]; then echo true; else echo false; fi
El primer ejemplo produce true
como resultado y el segundo ejemplo produce false
.
Ahora veamos su código. En su lugar, su declaración if tiene la siguiente expresión condicional:
[[ $gzip_file = "test_sub"*"gz" ]]
En particular, estás incluyendo "test_sub" como una subcadena en tu patrón de coincidencia. Intenta eliminar eso.
Respuesta2
Además de lo que dijo @igal sobre verificar la extensión del archivo, tiene muchos errores en la sintaxis y el uso de las variables. Comience con la línea 3:
L0_Report_Generator=("/home/ubuntu/$gzip_file")
La variable gzip_file
aún no se ha configurado, por lo que $gzip_file
no será reemplazada por nada cuando el shell la expanda. Además, el paréntesis var=(something)
asigna una matriz en lugar de una variable simple, y en este caso eso no tiene ningún sentido.
La cuarta línea, echo -n "Enter File Directory:"$gzip_file
tiene el mismo problema con la variable gzip_file
. También tiene el problema de que echo -n
es impredecible y hará cosas diferentes bajo diferentes versiones del echo
comando. Para imprimir una cadena sin salto de línea, es mucho mejor usar printf "%s" "string to print"
, pero en este caso hay una opción mejor a la que hablaré en un minuto.
La quinta línea read $gzip_file
, parece estar destinada a leer la entrada del usuario en la variable gzip_file
, pero eso no es lo que hace. En el shell, cuando pones $
delante de un nombre de variable, esoobtieneel valor actual de la variable. aquí quierescolocarasí que debes dejar apagado $
: read gzip_file
. Pero eso no es lo que haría. Incluiría el mensaje (que está echo
en la línea 4) como parte del read
comando:
read -p "Enter File Directory:" gzip_file
Bien, ahora para la línea 6:
for gzip_file in {$L0_Report_Generator}; do
Esto parece estar estableciendogzip_file
de nuevo(reemplazando el valor que acabamos read
de introducir). ¿Realmente estás intentando configurar gzip_file
aquí y las referencias de variables anteriores realmente deberían haber sido una variable diferente (tal vez gzip_dir
en su lugar)?
Además, la in
parte no tiene ningún sentido. Creo que estás intentando usar la variable L0_Report_Generator
, pero en ese caso la llave abierta debería irdespuésel signo del dólar. Pero eso tampoco tiene del todo sentido, porque ${L0_Report_Generator}
(si entiendo lo que se supone que debe hacer) será simplemente la ruta a un directorio. for ... in
no itera sobre el contenido de directorios, itera sobre una lista depalabras, como for var in word1 word2 "word 3 which has several spaces in it" word4; do
. Si desea obtener una lista de archivos en un directorio, necesita usar un comodín, como for var in dir/*; do
: el shell expandirá el patrón de archivo que contiene comodines en una lista de archivos coincidentes, cada uno tratado como una palabra, y los iterará sobre ellos. . También tiene la opción de limitar las coincidencias a archivos con una extensión específica incluyéndola en el patrón, como dir/*.gz
.
Otras tres notas: recomiendo no usar nombres de variables en mayúsculas como DATE
, para evitar conflictos con las diversas variables de entorno en mayúsculas que tienen un significado especial para el shell o algunas utilidades. Además, siempre coloque comillas dobles en las referencias de sus variables (es decir, use "$var"
en lugar de just $var
) para evitar rarezas inesperadas en el análisis. Y la else
cláusula no tiene prueba, por lo que usar else [[ some test ]]
no tiene sentido (y tener then
después else
es un error de sintaxis).
Entonces, si entendí lo que se supone que debe hacer el script, recomendaría reemplazar el comienzo del script con:
#!/bin/bash
date=$(date +%Y-%m-%d) # Note lowercase variable
read -p "Enter File Directory:" gzip_dir
L0_Report_Generator="/home/ubuntu/$gzip_dir"
for gzip_file in "${L0_Report_Generator}"/*.gz; do
...Y luego (si lo que desea es el patrón .gz anterior), no necesita if
verificar si $gzip_file
tiene una extensión .gz, porque el patrón comodín solo enumerará archivos .gz.
Una nota más:shellcheck.netes muy útil para señalar errores básicos en los scripts de shell. Se pierde mucho de lo que señalé, pero captó lo extraviado then
(que inicialmente me perdí).