开发者

Avoid trimming of bash $() output

开发者 https://www.devze.com 2023-01-29 01:41 出处:网络
From the Bash manual: Bash performs the expansion by executing command and replacing the command substitution with the standard

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消