Ana
Ana

Reputation: 533

how to output file names surrounded with quotes in SINGLE line?

I would like to output the list of items in a folder in the folowing way:

"filename1"  "filename2" "file name with spaces" "foldername" "folder name with spaces"

In other words, item names must be in a single line, surrounded with quotes (single or double) and divided by spaces.

I know that

find . | xargs echo

prints output in a single line, but I do not know how to add quotes around each item name.

This code is part of a bsh script. The solution can therefore be a set of commands and use temporary files for storing intermediate output.

Thank you very much for any suggestion.

Cheers, Ana

Upvotes: 53

Views: 54910

Answers (11)

Mark A. Donohoe
Mark A. Donohoe

Reputation: 30428

Try this...

find . -print0 | xargs -0 echo

the -print0 argument makes the output null-terminated instead of a new-line, and the -0 on xargs says to use null as the delimiter. As such, spaces are preserved as you would expect without the need to quote things.

Upvotes: 0

Michael Chen
Michael Chen

Reputation: 721

After 10 years, no one suggested the Bash "|while read" method?

find * -type d -depth 0|while read f; do echo \"$f\"; done

It's a simple Bash shell pipeline instead of launching another program like sed or xarg. If you really want to do something with each file/folder:

find * -type d -depth 0|while read f; do du -sh "$f"; done

By the way, find * uses another Bash feature that excludes .xyz files/folders and will not output the ./ prefix find . does.

Upvotes: 11

mpen
mpen

Reputation: 283043

To avoid hacks trying to manually add quotes, you can take advantage of printfs %q formatting option:

❯ ll .zshrc.d
total 112K
-rwxrwxrwx 1 root root  378 Jul  1 04:39  options.zsh*
-rwxrwxrwx 1 root root   57 Jul  1 04:39  history.zsh*
-rwxrwxrwx 1 root root  301 Jul  1 05:01  zinit.zsh*
-rwxrwxrwx 1 root root  79K Jul  1 05:19  p10k.zsh*
-rwxrwxrwx 1 root root  345 Jul  1 05:24  zplugins.zsh*
-rwxrwxrwx 1 root root  490 Jul  4 23:40  aliases.zsh*
-rw-r--r-- 1 root root 9.0K Jul 27 08:14  lscolors.zsh
-rw-r--r-- 1 root root    0 Aug 30 05:56 'foo bar'
-rw-r--r-- 1 root root    0 Aug 30 05:58 '"foo"'

❯ find .zshrc.d -exec printf '%q ' {} +
.zshrc.d .zshrc.d/history.zsh .zshrc.d/aliases.zsh .zshrc.d/zplugins.zsh .zshrc.d/p10k.zsh .zshrc.d/zinit.zsh .zshrc.d/options.zsh '.zshrc.d/"foo"' '.zshrc.d/foo bar' .zshrc.d/lscolors.zsh #

vs:

find .zshrc.d -printf "\"%p\" "
".zshrc.d" ".zshrc.d/history.zsh" ".zshrc.d/aliases.zsh" ".zshrc.d/zplugins.zsh" ".zshrc.d/p10k.zsh" ".zshrc.d/zinit.zsh" ".zshrc.d/options.zsh" ".zshrc.d/"foo"" ".zshrc.d/foo bar" ".zshrc.d/lscolors.zsh" #

Notice the file .zshrc.d/"foo" is incorrectly escaped.

❯ echo ".zshrc.d/"foo""
.zshrc.d/foo

❯ echo '.zshrc.d/"foo"'
.zshrc.d/"foo"

Upvotes: -1

Benjamin A.
Benjamin A.

Reputation: 967

You could also simply use find "-printf", as in :

find . -printf "\"%p\" " | xargs your_command

where:

%p = file-path

This will surround every found file-path with quotes and separate each item with a space. This avoids the use of multiple commands.

Upvotes: 65

iosuser2332
iosuser2332

Reputation: 41

    find . | sed "s|.*|\"&\"|"

Brief description:
We take result of .* pattern and put it into quotes.
Good source is sed.

Detail description:
Pattern: s/one/ONE/

  • s Substitute command.
  • / Delimiter.
    In my expression "|" is used instead of "/" to prevent "mountains" like in pattern s/.*/\"&\"/.
  • one Regular expression pattern search pattern.
  • ONE Replacement string.
  • .* Means any symbol that repeats unlimited number of times.
  • \" Means " itself.
  • & Special character that corresponds to the pattern found.

Upvotes: 1

Ferroao
Ferroao

Reputation: 3044

try

ls | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '

Upvotes: 1

George Hilliard
George Hilliard

Reputation: 15952

You can use the GNU ls option --quoting-style to easily get what you are after. From the manual page:

--quoting-style=WORD

use quoting style WORD for entry names: literal, locale, shell, shell-always, shell-escape, shell-escape-always, c, escape

For example, using the command ls --quoting-style=shell-escape-always, your output becomes:

'filename1' 'filename2' 'file name with spaces' 'foldername' 'folder name with spaces'

Using --quoting-style=c, you can reproduce your desired example exactly. However, if the output is going to be used by a shell script, you should use one of the forms that correctly escapes special characters, such as shell-escape-always.

Upvotes: 20

leesei
leesei

Reputation: 6070

EDIT:
The following answer generate a new-line separated LIST instead of a single line.

  1. I'm second guessing that the OP uses the result for invoking other command
  2. converting the output LIST to single line is easy (| tr '\n' ' ')

A less mentioned method is to use -d (--delimiter) option of xargs:

find . | xargs -I@ -d"\n" echo \"@\" 

-I@ captures each find result as @ and then we echo-ed it with quotes

With this you can invoke any commands just as you added quotes to the arguments.

$ find . | xargs -d"\n" testcli.js
[ "filename1",
  "filename2",
  "file name with spaces",
  "foldername",
  "folder name with spaces" ]

See https://stackoverflow.com/a/33528111/665507

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 247022

for f in *; do printf "'%s' " "$f"; done; echo

Or, thanks to Gordon Davisson:

printf "'%s' " *; echo

The trailing echo is simply to add a newline to the output.

Upvotes: 5

freethinker
freethinker

Reputation: 1306

this should work

find $PWD | sed 's/^/"/g' | sed 's/$/"/g' | tr '\n' ' '

EDIT:

This should be more efficient than the previous one.

find $PWD | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '

@Timofey's solution would work with a tr in the end, and should be the most efficient.

find $PWD -exec echo -n '"{}" ' \; | tr '\n' ' '

Upvotes: 33

Timofey Stolbov
Timofey Stolbov

Reputation: 4631

Try this.

find . -exec echo -n '"{}" ' \;

Upvotes: 20

Related Questions