Elvis Rock Code
Elvis Rock Code

Reputation: 26

Using command Output (with spaces) as other command Input (BASH)

Any one know why this works?

cat `echo "FilenameWithoutSpaces.txt"` # shows file content

stdout:

SHOW FILE CONTENT

And this not?

cat `echo "Filename\ With\ Spaces.txt"` # trying to show "Filename With Spaces.txt" content

stdout:

cat: 'Filename': No such file or directory

cat: 'With': No such file or directory

cat: Spaces.txt: No such file or director

What would be the correct way to pass an output (with spaces) as a input of another command?

The example above is a simplified case of what i need. What I have to to is:

To use list of files (that may contain spaces) returned by a command as argument for another command.

Upvotes: 1

Views: 1611

Answers (2)

William Pursell
William Pursell

Reputation: 212288

For this particular case:

cat "$(echo "Filename\ With\ Spaces.txt")"

Since the case is a bit contrived, I can't really say what the correct thing is for your actual situation. What is meant by a "list of files"? Is that a list of files that are separated by newlines? How will you handle files that contain a newline in the name? Is it a list of null separated files, or is the list comma separated? In general, my opinion would be that the correct solution is to ban the use of whitespace in filenames. If that's not an option, the general principle would be to always put quotes around any string that may contain elements of IFS.

However. (Note this "however" should be read as "the following is a terrible hack that should never be done because the correct approach is to ban the use of whitespace in filenames"). Assuming that by a "list of files" you mean that each name is distinguished from the next by the presence of a newline in the string, you might try something like:

printf '1st name\n2nd name\n' | { a=(); while read arg; do a+=("$arg"); done; 
    cmd "${a[@]}"
}

The above will invoke cmd with each line as a single argument. It would be much more reasonable to require that the list of inputs be zero separated, which would allow you to use xargs with something like:

printf '1st name\0002nd name\000' | xargs -0 cmd

Until you properly define what you mean by "list of files", no robust solution is possible.

Upvotes: 1

joshmeranda
joshmeranda

Reputation: 3251

This is due to the way strings are handled and passed are argument in bash. When you run echo "Filename\ With\ Spaces.txt" the output is Filename With Spaces.txt which is exaclty what you are expecting. So the full command is essentially the same as cat Filename With Spaces.txt and cat is trying to find 3 files with the names Filename, With, and Spaces.txt.

When bash looks for those is it not likely to find them and spits out those error messages you are seeing. When there are no spaces, the filename is read as a single parameter and so you do not encounter the same issue.

To force the command to work with and without spaces you need to add qutoations around the command substituion:

cat "`echo "Filename\ With\ Spaces.txt"`"

This command will expand the out put of the echo and keep it as a single argument.

Upvotes: 0

Related Questions