Extraiga el nombre del archivo de la ruta en el programa awk

21

Tengo un script awk y le he pasado un archivo CSV.

awk -f script.awk /home/abc/imp/asgd.csv

Lo que estoy haciendo es obtener FILENAME dentro script.awk. FILENAME me da todo el camino. Como estoy en awk no puedo usar basename FILENAME.

print FILENAME;
/home/abc/imp/asgd.csv

He intentado con esto dentro script.awk

echo $FILENAME | awk -F"/" '{print $NF}'

pero no puedo ejecutar esto dentro script.awk. ¿Cómo puedo acceder asgd.csva un programa awk?

Aashu
fuente

Respuestas:

33

Varias opciones:

awk '
  function basename(file) {
    sub(".*/", "", file)
    return file
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file

O:

awk '
  function basename(file, a, n) {
    n = split(file, a, "/")
    return a[n]
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file

Tenga en cuenta que esas implementaciones basenamedeberían funcionar para los casos comunes, pero no en casos de esquina como basename /path/to/x///donde devuelven la cadena vacía en lugar de xo /donde devuelven la cadena vacía en lugar de /, aunque para los archivos normales, eso no debería suceder.

El primero no funcionará correctamente si las rutas de los archivos (hasta el último /) contienen secuencias de bytes que no forman caracteres válidos en la configuración regional actual (normalmente, este tipo de cosas suceden en configuraciones regionales UTF-8 con nombres de archivos codificados en algunos 8). bit conjunto de caracteres de un solo byte). Puede solucionarlo fijando la configuración regional en C donde cada secuencia de bytes forma caracteres válidos.

Stéphane Chazelas
fuente
55
Si necesita código que va a funcionar fácilmente dentro de un script awk existentes sin introducir una función, se debe utilizar: n = split(FILENAME, a, "/"); basename=a[n];. No lo use subya que eso realmente cambiará la FILENAMEvariable (que no es un problema con la función ya que awk usa la llamada por valor).
shiri
10

Prueba este awk one-liner,

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
asgd.csv
Avinash Raj
fuente
3
oawk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv
Avinash Raj
0

la mejor manera de exportarlo desde el CSV de entrada o directamente desde la ruta del archivo de entrada puede invertirlo, luego obtener 1 columna y luego volverlo a invertir.

function getFileFromPath() {
    FileName=$1
    cat $FileName | while read Filename
    do
        echo $Filename| rev | awk -v FS='/' '{print $1}' | rev 
    done
}

o simplemente

echo $FileNamePath| rev | awk -v FS='/' '{print $1}' | rev 
FariZ
fuente
0

Utilice la función dividida de Awk

Una forma de hacerlo es usar la función de división. Por ejemplo:

awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' /path/to/file

Esto incluso funciona en múltiples archivos. Por ejemplo:

$ awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' \
      /etc/passwd /etc/group
passwd
group
CodeGnome
fuente
0

En los sistemas donde el basenamecomando está disponible, uno podría usar awkla system()función o expression | getline varestructura para llamar a un basenamecomando externo . Esto puede ayudar a tener en cuenta los casos de esquina mencionados en la respuesta de Stephane .

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Sergiy Kolodyazhnyy
fuente