Reputation: 316
I want to convert a string of paths (where each path may contain escaped spaces) into a printed list of paths. I'm mainly using echo
and sed
, and the problem lies therein (see below).
For example, I want these three files:
one two three\ two\ one
To be printed on three lines:
one
two
three two one
(1) These are three sample files: "one", "two", and "three two one".
echo "one two three\ two\ one"
# one two three\ two\ one
(2) I replace the whitespace that separates files with a newline.
echo "one two three\ two\ one" | sed 's/\([^\]\) /\1$'"'"'\\n'"'"'/g'
# one$'\n'two$'\n'three\ two\ one
(3) I test that indeed, "echoing" the output of the above results in the output I want.
echo one$'\n'two$'\n'three\ two\ one
# one
# two
# three two one
Combining (2) and (3), the functionality breaks using "xargs echo":
echo "one two three\ two\ one" | sed 's/\([^\]\) /\1$'"'"'\\n'"'"'/g' | xargs echo
# one$\ntwo$\nthree two one
How can the sed substitution be fixed so that echoing the output gives:
one
two
three two one
I'm looking for a solution that uses primarily "echo" and "sed" (not looking for other solutions).
I also can't use "echo -e" to interpret escaped characters.
Upvotes: 2
Views: 793
Reputation: 123550
Here's how you show your filenames on screen separated by linefeeds:
find "$PWD" -maxdepth 1 -print
If you wanted to process them in some way, you should pass them \0
separated (using -print0
) or use find -exec
. Trying to format them as shell words is not the way to go.
The reason why echo
doesn't show the value you expect is because $'\n'
is Bash syntax meaning literal linefeed. It is not echo
syntax, and echo
is not involved in interpreting it.
For dash
, xargs
and other more traditional tools, $'\n'
is just a weird way of formatting the literal characters dollar-backslash-n ($\n
).
Since you're using xargs echo
, bash
is not involved, so you get $\n
out instead. The solution is not to try to format data into code in such a way that the code will evaluate back to the original data. The solution is to skip that step entirely and just let data be data, such as in the initial example.
Upvotes: 1
Reputation: 360
Not a solution but an answer to the comment you made on your own post "on why xargs echo" isn't working, see this answer regarding what $'\n' is:
https://stackoverflow.com/a/4128305/4092051
Upvotes: 0
Reputation: 833
This command works for me:
echo "one two three\ two\ one" | sed 's/\([^\]\) /\1\n/g' | sed 's/\\ / /g' | xargs -L1 -I {} echo -{}-
The trick was
\\n
with \n
-L1
in xargs parameters{}
and -I{}
just to demonstrate that echo is called for each lineUpvotes: 0