Obtenir le dernier champ en utilisant awk substr

99

J'essaye d'utiliser awkpour obtenir le nom d'un fichier étant donné le chemin absolu vers le fichier.
Par exemple, quand on /home/parent/child/filenameme donne le chemin d'entrée que je voudrais obtenir, filename j'ai essayé:

awk -F "/" '{print $5}' input

qui fonctionne parfaitement.
Cependant, je suis un codage en dur $5qui serait incorrect si mon entrée a la structure suivante:

/home/parent/child1/child2/filename

Une solution générique nécessite donc de toujours prendre le dernier champ (qui sera le nom du fichier).

Existe-t-il un moyen simple de faire cela avec la fonction awk substr?

Mari
la source
2
comme quelqu'un l'a souligné, utiliser basenameest la façon officielle de le faire, utiliser awkpour cela n'est pas bon de le dire à la légère. : D
Kashyap

Réponses:

206

Utilisez le fait qui awkdivise les lignes en champs en fonction d'un séparateur de champ, que vous pouvez définir. Par conséquent, en définissant le séparateur de champ, /vous pouvez dire:

awk -F "/" '{print $NF}' input

comme se NFréfère au nombre de champs de l'enregistrement en cours, l'impression $NFsignifie l'impression du dernier.

Donc, étant donné un fichier comme celui-ci:

/home/parent/child1/child2/child3/filename
/home/parent/child1/child2/filename
/home/parent/child1/filename

Ce serait la sortie:

$ awk -F"/" '{print $NF}' file
filename
filename
filename
fedorqui 'Alors arrêtez de nuire'
la source
3
Cela fonctionne parfaitement. Je n'ai pas pensé à la variable $ NF. Merci pour votre réponse simple et efficace immédiate.
Mari
6
Pour l'avant-dernier, utilisez $(NF-1).
Itachi
1
J'écrivais un script pour fonctionner avec certaines commandes docker et cela a fait l'affaire. Merci!
Harlin
30

Dans ce cas, il vaut mieux utiliser basenameau lieu de awk:

 $ basename /home/parent/child1/child2/filename
 filename
piokuc
la source
4
@Mari FYI dirname fait le contraire et supprime le fichier et non le chemin.
Chris Seymour
5

Une autre option consiste à utiliser la bash substitution de paramètres .

$ foo="/home/parent/child/filename"
$ echo ${foo##*/}
filename
$ foo="/home/parent/child/child2/filename"
$ echo ${foo##*/}
filename
devnull
la source
5

Si vous êtes ouvert à une solution Perl, en voici une similaire à la solution awk de fedorqui:

perl -F/ -lane 'print $F[-1]' input

-F/spécifie /que le séparateur de champ
$F[-1]est le dernier élément du @Ftableau autosplit

Chris Koknat
la source
1
Merci. Cela m'a aidé à obtenir le dernier mais un champ. perl -F "/" -lane 'print $ F [-2]' entrée
riderchap
cela a fonctionné pour moi lors de la réception de l'entrée canalisée. Totalement oublié perl.
Christopher
3

Cela devrait être un commentaire à la réponse du nom de base, mais je n'ai pas assez de point.

Si vous n'utilisez pas de guillemets doubles, basename ne fonctionnera pas avec un chemin contenant un espace:

$ basename /home/foo/bar foo/bar.png
bar

ok avec guillemets ""

$ basename "/home/foo/bar foo/bar.png"
bar.png

exemple de fichier

$ cat a
/home/parent/child 1/child 2/child 3/filename1
/home/parent/child 1/child2/filename2
/home/parent/child1/filename3

$ while read b ; do basename "$b" ; done < a
filename1
filename2
filename3
Pierre-Damien
la source
3

Je sais que j'ai environ 3 ans de retard sur ce point, mais ... vous devriez envisager l'expansion des paramètres, elle est intégrée et plus rapide.

si votre entrée est dans un var, disons, $ var1, faites simplement ${var1##*/}. Regardez ci-dessous

$ var1='/home/parent/child1/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/child3/filename'
$ echo ${var1##*/}
filename
Adriano_Pinaffo
la source
2

Comme 5 ans de retard, je sais, merci pour toutes les propositions, j'avais l'habitude de le faire de la manière suivante:

$ echo /home/parent/child1/child2/filename | rev | cut -d '/' -f1 | rev
filename

Heureux de constater qu'il y a de meilleures manières

Nicko Glayre
la source
-1

Vous pouvez aussi utiliser:

    sed -n 's/.*\/\([^\/]\{1,\}\)$/\1/p'

ou

    sed -n 's/.*\/\([^\/]*\)$/\1/p'
SARATH
la source
1
À ce stade, personne n'a voté pour cette réponse, probablement parce qu'elle est relativement fugace :)
Josip Rodin