Extrair o nome do arquivo do caminho no programa awk

21

Eu tenho um script awk e passei um arquivo CSV para ele.

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

O que estou fazendo é colocar FILENAME dentro script.awk. FILENAME me fornece todo o caminho. Como estou no awk, não posso usar basename FILENAME.

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

Eu tentei com isso dentro script.awk

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

mas não posso executar isso por dentro script.awk. Como posso entrar asgd.csvem um programa awk?

Aashu
fonte

Respostas:

33

Várias opções:

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

Ou:

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

Observe que essas implementações de basenamedevem funcionar para os casos comuns, mas não nos casos de canto, como basename /path/to/x///onde eles retornam a cadeia vazia em vez de xou /onde retornam a cadeia vazia em vez de /, embora para arquivos regulares, isso não deva acontecer.

O primeiro não funcionará corretamente se os caminhos do arquivo (até o último /) contiverem seqüências de bytes que não formam caracteres válidos no código do idioma atual (normalmente esse tipo de coisa acontece nos códigos de idioma UTF-8 com nomes de arquivos codificados em cerca de 8 conjunto de caracteres de byte único). Você pode contornar isso fixando o código do idioma em C, onde cada sequência de bytes forma caracteres válidos.

Stéphane Chazelas
fonte
5
Se você precisa de código que irá trabalhar facilmente dentro de um script awk existente sem introduzir uma função, você deve usar: n = split(FILENAME, a, "/"); basename=a[n];. Não use, subpois isso realmente mudará a FILENAMEvariável (o que não é um problema da função, pois o awk usa a chamada por valor).
shiri 07/01
10

Experimente este awk one-liner,

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

a melhor maneira de exportá-lo do CSV de entrada ou diretamente do caminho do arquivo de entrada, você pode revertê-lo, obter uma coluna e inverter novamente.

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

ou simplesmente

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

Use a função Split do Awk

Uma maneira de fazer isso é usar a função de divisão. Por exemplo:

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

Isso funciona mesmo em vários arquivos. Por exemplo:

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

Nos sistemas em que o basenamecomando está disponível, pode-se usar awka system()função ou expression | getline varestrutura de para chamar o basenamecomando externo . Isso pode ajudar a explicar os casos extremos mencionados na resposta de Stephane .

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