Avoid trimming of bash $() output
From the Bash manual:
Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.
That means obscure bugs are possible when handling output with meaningful trailing newlines. A contrived example:
user@h开发者_运维知识库ost:~$ path='test
'
user@host:~$ touch -- "$path"
user@host:~$ readlink -fn -- "$path"
/home/user/test
user@host:~$ full_path="$(readlink -fn -- "$path")"
user@host:~$ ls -- "$full_path"
ls: cannot access /home/user/test: No such file or directory
Any tips on how to assign the value of a command to a variable without losing semantically useful data?
The adventures of Bash continue another day!
You could use quoting and eval
to work around this. Change your last two commands to:
full_path="'$(readlink -fn -- "$path"; echo \')"
eval ls -- "$full_path"
If you want the result with trailing newlines in a variable you could first add a bogus character (in this case underscore) and then remove that.
full_path="$(readlink -fn -- "$path"; echo _)"
full_path=${full_path%_}
ls -- "$full_path"
I have no good answers. However, this hack will work for both files with and without newlines in the name.
path='test
'
touch -- "$path"
readlink -fn -- "$path"
full_path=
if [[ $path =~ $'\n' ]] ; then
while IFS=$'\n' read fn ; do
full_path+="$fn"$'\n'
done < <(readlink -fn -- "$path")
else
full_path="$(readlink -fn -- "$path")"
fi
ls -l -- "$full_path"
One (deprecated) way could be to use back-quotes instead of $(); try:
full_path=`readlink -fn -- $path`
$ readlink -f "$path"
This return the good path. I don't know why you used the -n option with readlink because it removes newlines.
Unfortunatly when I store the result of this command the newline seems to be removed
$ fullpath=`readlink -f "$path"`
$ echo "$fullpath"
/home/test
No newlines. I don't know if it's "echo" or the way to store that remove the newline at the end of the path.
$ ls
test?
$ls test?
test?
Newline seems to be replaced by ?. May be there is something to do with it.
精彩评论