$ ls > file
doesn't do what you expect:
$ touch foo $ touch bar $ ls > filelist $ cat filelist bar filelist foo
You probably didn't expect, or want,
filelist to be listed in
$ filelist=$(ls); echo "$filelist" >filelist
Store the output of
ls into a variable before writing out to
the file, so the file doesn't exist yet when running
ls. This can
be split into two lines:
$ filelist=$(ls) $ echo "$filelist" >filelist
but just leaving out the semicolon doesn't work:
$ filelist=INCORRECT $ filelist=$(ls) echo "$filelist" >filelist $ cat filelist INCORRECT
Why list into a file?
Usually when I am redirecting
ls's output to a file, it's to compare
with a directory on another computer:
$ scp remote:/path/to/filelist . $ ls | diff - filelist ...
A too simple workaround
The simple and obvious workaround is to just put the file in a different directory. Either
$ ls path/to/the/directory > filelist
$ ls > path/to/filelist
filelist in a different directory so it would never be
included in the list. But just pointing out that what we want to do is
probably the wrong thing is not really an answer.
A broken workaround
$ ls | tee filelist >/dev/null $ cat filelist bar foo
tee means that the file isn't created until after
tee starts running, while with the redirection, the file is
sh before it runs
the file list soon after it starts and it runs quickly, so it will often
But relying on the scheduler is always a bad idea, and, empirically, it rarely actually works.
The actual fix
Because we really want
ls to finish before there's any chance of
the file being created, we just store its result in a variable before
writing the file. There is one detail to note:
$ filelist=$(ls) $ echo $filelist bar foo $ echo "$filelist" bar foo
You need the quotes around
$filelist or the
newlines will turn into spaces because the quotes make it get sent to
echo as a single argument instead of a list of arguments and
echo outputs its arguments separated by spaces.
$ ps x | grep vim 15888 pts/29 S+ 0:00 grep --color=auto --exclude-dir=.svn vim 18137 ? Ssl 0:00 gvim ../test.sh
grep process when you probably didn't want it.
There's workarounds that involve carefully crafting regular expressions
that don't match themselves:
$ ps x | grep vi[m] 18137 ? Ssl 0:00 gvim ../test.sh
But that's a messy hack. Instead you can use
ps -C. Why are there
three very similar commands to do the same thing? Sorry, I have no idea.