AWK: get file name from LS

awk print filename
ls awk
awk print filename if match
awk list file names
awk function
awk '(print filename with spaces)
bash get filename from path
ls filename

I have a list of file names (name plus extension) and I want to extract the name only without the extension.

I'm using

ls -l | awk '{print $9}' 

to list the file names and then

ls -l | awk '{print $9}' | awk /(.+?)(\.[^.]*$|$)/'{print $1}'

But I get an error on escaping the (:

-bash: syntax error near unexpected token `('

The regex (.+?)(\.[^.]*$|$) to isolate the name has a capture group and I think it is correct, while I don't get is not working within awk syntax.

My list of files is like this ABCDEF.ext in the root folder.

Try this.

ls -l | awk '{ s=""; for (i=9;i<=NF;i++) { s = s" "$i }; sub(/\.[^.]+$/,"",s); print s}'


  1. read the ls -l output is weird
  2. It doesn't check the items (they are files? directories? ... strip extentions everywhere)
  3. Read the other answers :D

How to print filename with awk on Linux / Unix, Explains how to print filename with awk on Linux, macOS, *BSD and So you need to modify it as follows (assuming that ls -l only produced a  awk '{print substr($0, index($0,$9))}' For example this is the output of ls command:-rw-r--r--. 1 root root 73834496 Dec 6 10:55 File with spaces 2. If you use simple awk like this # awk '{print $9}' It returns only # File If used with the full command # awk '{print substr($0, index($0,$9))}' I get the whole output. File with spaces 2

Your specific error is caused by the fact that your awk command is incorrectly quoted. The single quotes should go around the whole command, not just the { action } block.

However, you cannot use capture groups like that in awk. $1 refers to the first field, as defined by the input field separator (which in this case is the default: one or more "blank" characters). It has nothing to do with the parentheses in your regex.

Furthermore, you shouldn't start from ls -l to process your files. I think that in this case your best bet would be to use a shell loop:

for file in *; do
  printf '%s\n' "${file%.*}"

This uses the shell's built-in capability to expand * to the list of everything in the current directory and removes the .* from the end of each name using a standard parameter expansion.

If you really really want to use awk for some reason, and all your files have the same extension .ext, then I guess you could do something like this:

printf '%s\0' * | awk -v RS='\0' '{ sub(/\.ext$/, "") } 1'

This prints all the paths in the current directory, and uses awk to remove the suffix. Each path is followed by a null byte \0 - this is the safe way to pass lists of paths, which in principle could contain any other character.

Slightly less robust but probably fine in most cases would be to trust that no filenames contain a newline, and use \n to separate the list:

printf '%s\n' * | awk '{ sub(/\.ext$/, "") } 1'

Note that the standard tool for simple substitutions like this one would be sed:

printf '%s\n' * | sed 's/\.ext$//'

How to output only file names (with spaces) in ls -Al?, Why don't you do something like this: The good find ./ -printf "%f\n". or for n in *;​  I would like to print filename with awk on Linux / Unix-like system. How do I print filename in BEGIN section of awk? Can I print the name of the current input file using gawk/awk? The name of the current input file set in FILENAME variable. You can use FILENAME to display or print current input file name If no files are specified on the

(.+?) is a PCRE construct. awk uses EREs, not PCREs. Also you have the opening script delimiter ' in the middle of the script AFTER the condition instead of where it belongs, before the start of the script.

The syntax for any command (awk, sed, grep, whatever) is command 'script' so this should be is awk 'condition{action}', not awk condition'{action}'.

But, in any case, as mentioned by @Aaron in the comments - don't parse the output of ls, see

Bash Script Extract Filename from ls -l Results, this should print all the paths of the files modified between the given dates: find . -​type f -newermt '2018-01-17' ! -newermt '2018-01-18'. That's close, but the ls -la output is already in a file. So I just want to run awk against that file and strip out everything before the filename (the 9th field) on each line. Edit: Looks like this will work: awk '{print $9}' file > newfile. Last edited by chudster; 10-07-2010 at 06:27 PM.

If the extension is always the same pattern try a sed replacement:

ls -l | awk '{print $9}' | sed 's\.ext$\\'

AWK and file names with space in it., ls | awk -F\. '{print $1}'. After i run this in console evething is ok and I get file name whithout extension. Example: file 11237_712312955_2012-01-04 18_31_03. ex. testfile_041504_003567 To load the filename into Oracle I thought about using awk to place the filename before every record in the file and then I can load it based on the position. This portion works ok, but I'm stuck with the hard part. awk ' {print FILENAME,$0} ' filename> filename.dat I tested this process manually, by typing in the

grep and awk showing filename in loop, for filename in `ls -1 *.txt' do grep search_text $filename | awk '{print $3" "$4}' done. This displays the 3rd and 4th field of all lines in the list of files as in: ls -l | sed s/\ /{space}/ | awk '{print $9}' | sed s/{space}/\ / This will replace all spaces in a line with {space} before passing it to awk. After the line has passed to awk, we replace {space} back with space. find as stated by others is a much better solution. But if you really have to use awk, you can try this.

To cut the file name from the ls, i need to cut only filename from the available file variable not file you got your ls -l output is a pipe with awk to get the 9th field: e.g. with ls -l ->. In the above example, awk fails to process fields properly because the fields are separated by newlines and not spaces. You need to set the FS to the newline ( ) and the RS to a blank text, so empty lines will be considered separators. $ awk 'BEGIN{FS=" "; RS=""} {print $1,$3}' addresses

How to limit output of ls to only show filename, date and size , ls -l | awk '{print $5, $6, $7, $9}'. This will print the file size in bytes, month, date, and filename. jin@encrypt /tmp/foo % ls -l total 0 drwxr-xr-x 2 jin wheel 68 Oct 4  ls + awk + grep Hi All, I ran this command, root::> ls -lrt *filename* | awk '{print $5}' and this is the output that I received, 249 1221 681 141 357 681 0 0 0 0 0 0 0 0 0 0 0 How can I modify the command so that it will only capture 0 and not any other numbers (e.g 10, 100, 100 or any numbers; except for 0 only).

  • Don't parse the output of ls !.
  • okay, but the error here is not caused by that one, since it has been already parsed by awk '{print $9}' , isn'it?
  • No, parsing the output of ls isn't causing your immediate error, but it's likely to cause some others along the road. The linked article showcases a few way to deal with lists of files you might want to adopt instead of ls, which would make fixing your current error unnecessary :)
  • Why aren't there quotes around the regex?
  • because I was wrong about awk syntax: awk 'condition{action}'
  • @loretoparisi It's really not - there is absolutely no need to use ls -l and as numerous people including myself have mentioned, it is problematic.
  • You have GOT to be kidding. This is every bit as bad as that awk+sed answer you had previously accepted but just in different ways. Among other things it'll convert all chains of contiguous white space in file names to a single blank char each, and it'll still fail by starting at the wrong string given the different timestamp formats that ls -l outputs.
  • right $1 does not match the capture group infact, that is why it is not working the fixed one ls -l | awk '{print $9}' | awk '/(.+?)(\.[^.]*$|$)/{print $0}'
  • I'm not sure what you mean, but anything starting with ls -l | and multiple awks is almost certainly not the best solution. I suggest you try out the loop in my answer.
  • I partially agree, because my question was about using awk with ls. I agree that ls is the wrong choice, but strictly answering this question (should) implies the use of ls plus awk, but you were absolutely right about the optimal answer.
  • thanks for some reason by the way I don't get it working like ls -l | awk '{print $9}' | awk '/(.+?)(\.[^.]*$|$)/{print $0}'.
  • for some reason? I told you at least one reason: (.+?) is a PCRE construct and awk uses EREs, not PCREs. Since you haven't provide any sample input or expected output or told us what it is you're trying to do or in what way that isn't working, there's nothing more I can do to help you debug it or do whatever it is you're trying to do the right way (other then reiterate don't parse the output of ls).