Extraire le nom de fichier du chemin dans le programme awk

21

J'ai un script awk et je lui ai transmis un fichier CSV.

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

Ce que je fais, c'est de faire entrer FILENAME script.awk. FILENAME me donne tout le chemin. Comme je suis en awk, je ne peux pas l'utiliser basename FILENAME.

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

J'ai essayé avec ça en dedans script.awk

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

mais je ne peux pas exécuter cela à l'intérieur script.awk. Comment puis-je accéder asgd.csvà un programme awk?

Aashu
la source

Réponses:

33

Plusieurs options:

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

Notez que ces implémentations de basenamedevraient fonctionner pour les cas courants, mais pas dans les cas d'angle comme basename /path/to/x///où ils renvoient la chaîne vide à la place xou /où ils renvoient la chaîne vide à la place /, bien que pour les fichiers normaux, cela ne devrait pas se produire.

Le premier ne fonctionnera pas correctement si les chemins de fichier (jusqu'au dernier / ) contiennent des séquences d'octets qui ne forment pas de caractères valides dans les paramètres régionaux actuels (généralement ce genre de chose se produit dans les paramètres régionaux UTF-8 avec des noms de fichiers codés dans 8 jeu de caractères à un seul octet). Vous pouvez contourner cela en fixant les paramètres régionaux à C où chaque séquence d'octets forme des caractères valides.

Stéphane Chazelas
la source
5
Si vous avez besoin du code qui fonctionnera facilement dans un script awk existant sans introduire une fonction, vous devez utiliser: n = split(FILENAME, a, "/"); basename=a[n];. Ne pas utiliser subcar cela changera réellement la FILENAMEvariable (ce qui n'est pas un problème avec la fonction car awk utilise l'appel par valeur).
shiri
10

Essayez ce awk one-liner,

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

la meilleure façon de l'exporter depuis le CSV d'entrée ou directement depuis le chemin du fichier d'entrée, vous pouvez l'inverser, puis obtenir 1 colonne, puis l'inverser à nouveau.

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

ou simplement

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

Utilisez la fonction Split d'Awk

Pour ce faire, vous pouvez utiliser la fonction de partage. Par exemple:

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

Cela fonctionne même sur plusieurs fichiers. Par exemple:

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

Sur les systèmes où basename commande est disponible, on pourrait utiliser awkla system()fonction ou la expression | getline varstructure de pour appeler une basenamecommande externe . Cela peut aider à rendre compte des cas d'angle mentionnés dans la réponse de Stéphane .

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