Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I should echo only names of files or directories with this construction:

ls -Al | while read string

ls -Al output :

drwxr-xr-x  12 s162103  studs         12 march 28 12:49 personal domain
drwxr-xr-x   2 s162103  studs          3 march 28 22:32 public_html
drwxr-xr-x   7 s162103  studs          8 march 28 13:59 WebApplication1

For example if I try:

ls -Al | while read string
echo "$string" | awk '{print $9}

then output only files and directories without spaces. If file or directory have spaces like "personal domain" it will be only word "personal".

I need very simple solution. Maybe there is better solution than awk.

share|improve this question
Why not just ls -Al *' '*? Parsing ls's output never leads to anything good. – manatwork Mar 30 '13 at 15:01
If you need something that will work in any *nix try avoiding using ls -Al | while. A simple and more reliable way is for string in *; do echo "$string"; done. – forcefsck Mar 30 '13 at 15:17
need only with this construction..okay,not simple,any solution! – Alex Zern Mar 30 '13 at 15:31
Why do you need ls? Parsing ls and "work in all *nix and will not break if something happened" do not go well together. – terdon Mar 30 '13 at 15:59
1 – Braiam May 10 '14 at 23:29

6 Answers 6

You really should not parse the output of ls. If this is a homework assignment and you are required to, your professor does not know what they're talking about. Why don't you do something like this:

The good...

find ./  -printf "%f\n"


for n in *; do echo "$n"; done

...the bad...

If you really really want to use ls and need to make it robust, you are going to have to do something like this:

ls -lA | gawk -F':[0-9]* ' '/:/{print $2}'

...and the ugly

If you insist in doing it the wrong, dangerous way and just have to use a while loop, do this:

  ls -Al | while IFS= read -r string; do echo "$string" |  
      gawk -F':[0-9]* ' '/:/{print $2}'; done

Seriously though, just don't.

share|improve this answer
drwx------ 2 s162103 studs 3 oct. 9 2012 .ssh drwxr-xr-x 3 s162103 studs 6 oct. 25 09:02 .subversion drwxrwxrwt 3 s162103 studs 3 nov. 15 2012 .TempoItems sometimes i've got date without time, only year and gawk return empty – Alex Zern Mar 30 '13 at 16:30
@AlexZern Well, that's one of the reasons you don't parse the output of ls. – terdon Mar 30 '13 at 16:33
@AlexZern why do you need the -l switch anyway? If all you want is the file names, just run ls -A. Using -l just makes your life harder since you now have to parse the output. – terdon Mar 30 '13 at 16:37
because I need additional information like access, date, owner,etc. And I wrote a huge script ,which works well, except print file and dir names with spaces. – Alex Zern Mar 30 '13 at 16:46
OK then. What we have here is an XY problem. ls is just not the best way of getting what you need. Why don't you post a new question explaining the information you want to collect and we can suggest ways of doing it. Alternatively, you can use your script as is, and use one of the suggestions above to print the name only. But seriously, don't parse ls, just tell us exactly what you are trying to do in a new question. – terdon Mar 30 '13 at 16:49

Is there some reason that ls -A1* won't work?


$ touch file1 file2 file\ with\ spaces
$ ls -Al
total 0
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file1
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file2
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file with spaces
$ ls -A1
file with spaces

* Note: that's a capital letter A and the number one.

share|improve this answer
the -1 is genius. I didnt know that was available. (I know I know. RTFM) – The Lazy Coder Aug 20 at 16:38
that only works for current directory if you want to list file names from other directory say ~/projects then you will get full paths instead of file names – thecotne yesterday

How about:

for file in * .[!.]*
  printf "%s\n" "$file"
share|improve this answer

You cannot parse the output of ls, let alone ls -l because newline, just like space is as valid a character as any in a filename. Also, you'll need to consider symlinks that have an output like ... foo -> bar.

Why would you use -l anyway if you only want the file name?

Just do:

for file in *; do

If you want to include dot files, depending on the shell:


for file in *(D); do


shopt -s dotglob
for file in *; do


for file in *; do


for file in .[!.]* ..?* *; do
  [ -e "$file" ] || [ -L "$file" ] || continue
share|improve this answer

Try (bash, zsh, ksh93 syntax):

find . -type f -print0 | while IFS= read -r -d '' filename; do

This goes recursive and lists only on normal files (i.e. no dirs or symlinks/fifos/devices...).

See also:

share|improve this answer
ls -Al | tr -s ' ' | cut -f9- -d' '

compress multiple spaces into single spaces with tr then you can use cut to split on the fields

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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