0

i have some files in a folder and i want to print thier names in one file.txt in tabulary way like a text not one under one , is there any command for that ?

dd1.txt dd2.txt dd3.txt dd5.txt
6
  • 1
    ls -l dd*.txt > file.txt?
    – Panki
    Aug 1 '21 at 15:33
  • 2
    Do you need all on a single line or do you want to break the line as ls would ordinarily do? Do you need a specific delimiter between the names to separate them? How do you want to handle names that embed that delimiter?
    – Kusalananda
    Aug 1 '21 at 15:36
  • all in one single line and separated with space that's all ! . thank you . Aug 1 '21 at 15:45
  • 1
    If the filenames do not ever include spaces, echo * > file.txt might be enough. Aug 1 '21 at 16:13
  • 1
    ls -w0 dd*.txt will display as if your terminal was infinitely wide (though with wrapround). However, redirection to a file will behave like ls -1. Aug 1 '21 at 16:19
2

Assuming there's no need for recursing down into subdirectories:

printf '%s\n' * | paste -d ' ' -s - >other/path/file.txt

This would list all the visible filenames from the current directory on a single line in the file other/path/file.txt.

I'm choosing to write to a file in some other directory, as writing to file.txt in the current directory would make that filename part of the output. Make sure that the output filename is free to use first, obviously.

The printf utility is usually a built-in utility in the shell, so it would be able to handle this even though * may expand to many thousand names (note that printf is not a built-in utility in sh or ksh on OpenBSD though). The utility generates a filename per line, but without interfering with the formatting of the names themselves, which ls may be doing under some circumstances.

The paste command takes the newline-delimited list of names and puts them on a single line with spaces in-between them. The delimiter is easily changed using the -d option, if needed.

This would not properly handle filename with embedded newline characters, nor would it be possible to extract filenames with embedded spaces from the generated list.

1
  • Note that it would print a line containing a litteral * if the current directory contained no visible file (contained only hidden file or was not readable by the current user) Aug 1 '21 at 21:49
2
$ files=(*)
$ echo "${files[@]}"
dd1.txt dd2.txt dd3.txt dd5.txt
3
  • 1
    That assumes the first filename is not something like -n, -neenEn... and/or that none of the file names contain backslash characters, depending on the echo/shell implementation and/or runtime/compilation options. With ksh/zsh, print -r - "${files[@]}" ("${files[@]}" is ksh syntax already). With bash (and provided the posix and xpg_echo options are not both on): echo -nE "${files[@]}"$'\n'. Aug 1 '21 at 17:54
  • 1
    Also note that with some shells and with their default options, that would output *<newline> if the current working directory contained no non-hidden file. Aug 1 '21 at 17:56
  • @StéphaneChazelas all true, thanks for mentioning it. I think it's probably adequate for the OPs needs anyway but we'll see if it turns out otherwise.
    – Ed Morton
    Aug 1 '21 at 17:59
1

To print the names of the non-hidden files in the current directory, sorted lexically, separated by space characters and terminated with a newline character, with the zsh shell, you can do:

print -r - *(N)

Or:

echo -E - *(N)

With the fish shell:

set files *; echo -E -- $files

With the ksh93 shell:

print -r - ~(N)*

With the yash shell:

(set -o nullglob; ECHO_STYLE=raw echo *)

With bash, and provided the posix and xpg_echo options are not both enabled (as it is by default in some deployments of bash):

(shopt -s nullglob; set -- *; echo -En "$@"$'\n')

Or:

POSIXly (so would also work in bash (even when not in POSIX mode) and zsh (but only if in POSIX mode)):

set -- [*] *
case "$1$2" in
  ('[*]*') printf '\n';;
  (*) 
    printf %s "$2"
    shift 2
    printf ' %s' "$@"
esac
printf '\n'

(bearing in mind that that one may fail in shell implementations where printf is not builtin and if there is a large number of files in the current working directory).

Note that all those will print an empty line if the current working directory does not contain non-hidden files or is not readable. In any case, the output will only contain one line if none of the file names contain newline characters.

It may come as a surprise that such a simple task should be so hard to do with standard shells, but here we have to work around a few misdesigns of Unix shells and utilities:

  • that echo (the command meant to output arguments separated by spaces) is one of the most unportable one and where the standard implementations do more than required in a way that can't easily be disabled.
  • that many shells including the POSIX sh specification leave globs unexpanded when they don't match.
  • that ls, the command to list files, doesn't have any way to produce that list in a format that is post-processable.
  • that lines cannot contain any arbitrary sequence of bytes (that's the case of text line representations on most systems, not limited to Unix let alone Unix utilities though).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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