I have an awk script and I have passed a CSV file to it.

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

What am I doing is to get FILENAME within script.awk. FILENAME gives me the whole path. As I am in awk I cannot use basename FILENAME.


I have tried with this within script.awk

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

but I cannot execute this within script.awk. How can I get asgd.csv within an awk program?


Several options:

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


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

Note that those implementations of basename should work for the common cases, but not in corner cases like basename /path/to/x/// where they return the empty string instead of x or / where they return the empty string instead of /, though for regular files, that should not happen.

The first one will not work properly if the file paths (up to the last /) contain sequences of bytes that don't form valid characters in the current locale (typically this kind of thing happens in UTF-8 locales with filenames encoded in some 8 bit single byte character set). You can work around that by fixing the locale to C where every sequence of byte form valid characters.

|improve this answer|||||
  • 5
    If you need code that will work easily within an existing awk script without introducing a function, you should use: n = split(FILENAME, a, "/"); basename=a[n];. Don't use sub as that will actually change the FILENAME variable (which is a non-issue with the function since awk uses call by value). – shiri Jan 7 '18 at 9:28

Try this awk one-liner,

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
|improve this answer|||||
  • 3
    or awk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv – Avinash Raj Jun 3 '14 at 8:39

On the systems where basename command is available, one could use awk's system() function or expression | getline var structure to call external basename command. This can help accounting for corner cases mentioned in Stephane's answer.

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
|improve this answer|||||
  • This should be top answer. It's much safer to get basename command than to split by slashes and hope that there is no \/ in the filename – Karel Bílek Mar 16 at 11:59

the best way to export it from input CSV or directly from input file path you can reverse it , then get 1 column and then again reverse it.

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

or simply

echo $FileNamePath| rev | awk -v FS='/' '{print $1}' | rev 
|improve this answer|||||

Use Awk's Split Function

One way to do this is to use the split function. For example:

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

This even works on multiple files. For example:

$ awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' \
      /etc/passwd /etc/group
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.