In ls *.fits, it's the shell that does all the hard work finding the filenames that end in .fits and don't start with ..
Then it passes that list to ls, which sorts it (again, as shell globs already sort the list before passing to ls) and displays it (in columns or one per line depending on the implementation and whether the output goes to a terminal or not) after having checked that each file exists.
So it's a bit counter-productive especially considering that:
- you forgot the
-- option delimiter, so any filename starting with - would cause problems.
- you forgot the
-d option, so if any file is of type directory, ls would list their contents instead of themselves.
- as
ls is a separate command from the shell (in most shells including bash), it ends up having to be executed in a separate process using the execve() system call and you end-up tripping its limit on the cumulative size of arguments and environment variables.
If you just need to print the list generated by the shell from *.fits, you can use printf instead which is built-in in most shells (and therefore doesn't invoke execve() and its limit):
printf '%s\n' *.fits > output_all.txt
That leaves one problem though:
If *.fits doesn't match any file, in the bash shell, *.fits is left as-is, so printf will end-up printing *.fits<newline>.
While ls would give you an error message about that non-existent *.fits file and leave the output_all.txt empty.
That can be changed with the nullglob option (which bash copied from zsh) which causes *.fits to expand to nothing instead. But then we run into another problem: when not passed any argument beside the format, printf still goes through the format once as if passed empty arguments, so you'd end up with one empty line in output_all.txt.
That one can be worked around with:
shopt -s nullglob
println() {
[ "$#" -eq 0 ] || printf '%s\n' "$@"
}
println *.fits > output_all.txt
If you can switch to zsh instead of bash, it becomes easier:
print -rC1 -- *.fits(N) > output_all.txt
Where N enables nullglob for that one glob and print -rC1 prints its arguments raw on 1 Column, and importantly here: prints nothing if not passed any argument.
With zsh, you can also restrict the list to regular files only (excluding directories, symlinks, fifos..) using the . glob qualifier (*.fits(N.) for instance), or include hidden files with D (*.fits(ND.))...
Lastly you can also always defer to find to find the files, but if you do need the list to be sorted and hidden files to be excluded, and avoid a ./ prefix, that becomes quickly tedious as well and you'd need GNU extensions. For example, for the equivalent of print -rC1 -- *.fits(N.):
LC_ALL=C find . -maxdepth 1 ! -name '.*' -type f -printf '%P\0' |
sort -z | tr '\0' '\n' > output_all.txt
ls | grep .fits$ > output_all.txtwork? – Bib Nov 26 '21 at 15:45