What does the following command do in Linux?
ls * > file1
Does it simply copy all the file names in the current directory into a new file?
What does the following command do in Linux?
ls * > file1
Does it simply copy all the file names in the current directory into a new file?
This lists all the files in the current directory as well as subdirectories (1 level below current directory, not recursive), and then redirects the standard output from the ls
program to a file named file1
If you want to list all the non-hidden names in the current directory, one line at a time, and write that list into a new file list
, use
ls >list
This would list all names in the current directory and write them out to the file called list
. The list would contain the name of the list
file itself.
If you want to include hidden names, use ls -a
(or ls -A
to not include the .
and ..
entries).
Note that the list
file, once created, would be more or less useless other than for reading with your eyes, unless you can guarantee that none of the filenames contain embedded newlines.
The command you show contains several parts that the shell will act on before considering what the actual command does. The final result of the command depends on the current state of the shell, the names and types of the files in the current directory, and the permissions on the output file and the current directory.
The redirection to file1
is acted upon first. If the file with that name already exists, it will be truncated (emptied), otherwise it will be created. The shell will later connect the standard output stream of the command to this file, and all output of the command will be saved there.
If the name file1
corresponds to a directory, if it corresponds to a write-protected file, or if the output file can't be created due to the permissions on the current directory, then the shell will emit an error message. In this case, it would also stop the processing of the command at this point.
Before the shell can run the command, it must figure out all its arguments (note that the >
and the subsequent file1
are not arguments to the ls
command). In this case, the command line contains the unquoted globbing pattern *
, and the shell replaces this with the names that this pattern matches. By default, *
would match all non-hidden names in the current directory. A user may modify this by setting various shell options so that the pattern also matches hidden names or so that the pattern is not considered for filename globbing at all.
If the pattern does not match any names, it is by default kept unexpanded as a literal *
character. This depends on the shell options set in the current shell. Other possible scenarios include that the pattern is completely removed or that the shell emits an error message and stops the processing of the command at this point.
The shell finally looks up ls
among the currently defined aliases, shell functions, and built-in utilities. If it can't find a name that corresponds to ls
, it tries to find an executable file in the directories listed in the value of the PATH
variable. If no such executable can be found, the shell emits an error message and stops processing the command at this point. Some shells might continue processing by running various hooks that suggest alternative spellings of known commands or propose that the user installs the correct software packages, etc.
The ls
command, when found, is given whatever *
possibly expanded to (depending on the settings of the current shell session) as argument(s), and the command does its thing.
Assuming ls
resolves to the standard ls
command, it would list each argument in turn. This would involve outputting the names of non-directories and the contents of any directory argument. If an argument is a symbolic link to a directory, the contents of that directory would also be outputted.
If *
on the command line resolves to something that starts with a dash, then ls
may interpret that as an option rather than a filename. This may alter the result of the command.
If *
was kept unexpanded due to filename globbing having been turned off, and if there was no file (regular or otherwise) named *
in the current directory, then the ls
command would emit an error message on its standard error stream.
If *
was removed because it did not match anything and the shell was configured to remove non-matching patterns, the ls
command would list the contents of the current directory (likely producing no output).
By virtue of the redirection processed in the first step, whatever output the command produces on its standard output stream will end up in that file.
*
expands to nothing (when there are no non-hidden files and globbing is configured or happens to expand to nothing upon no-match), then ls
will list the current working directory. Also if *
expands to one and only one file and if it's of type directory, then it will list its contents but not add a dirname:
header above it, so you won't know what directory it listed. You may want to add in conclusion that it's incorrect code, possibly a misguided attempt to list the contents of the current directory which should have just been ls > file
.
– Stéphane Chazelas
Jan 29 '22 at 07:39
-l
/ -F
(and a few others), ls symlink-to-dir
will list the contents of the directory the symlink points to, not the symlink itself. In interactive shells, ls
is often aliases to ls -F
(or ls -F --color
, etc, intended to make it more user friendly) which affects that behaviour (and the output).
– Stéphane Chazelas
Jan 29 '22 at 07:44
man ls
if they need this much detail when documentation is freely available.
– dcom-launch
Jan 31 '22 at 22:04
ls(1)
manual won't say anything at all about the rest.
– Kusalananda
Jan 31 '22 at 22:22
https://www.gnu.org/software/bash/manual/html_node/Redirections.html
man ls
file2
when youcat file1
and yes, only the name(file2
). – Riz Jan 28 '22 at 19:17