我的 bash 脚本接收字符串形式的文件名(或相对路径),但必须从该文件中读取。如果我直接在脚本中将其声明为文字(不带引号),我只能从文件名中读取...这对于参数来说是不可能的,因为它们一开始就是隐式字符串。观察:
a="~/test.txt"
#Look for it
if [[ -a $a ]] ; then
echo "A Found it"
else
echo "A Error"
fi
#Try to use it
while read line; do
echo $line
done < $a
b='~/test.txt'
#Look for it
if [[ -a $b ]] ; then
echo "B Found it"
else
echo "B Error"
fi
#Try to use it
while read line; do
echo $line
done < $b
c=~/test.txt
#Look for it
if [[ -a $c ]] ; then
echo "C Found it"
else
echo "C Error"
fi
#Try to use it
while read line; do
echo $line
done < $c
产量:
A Error
./test.sh: line 10: ~/test.txt: No such file or directory
B Error
./test: line 12: ~/test.txt: No such file or directory
C Found it
Hello
如上所述,我无法将命令行参数传递给上面的例程,因为我得到的行为与在带引号的字符串上得到的行为相同。
这是
~
扩展规则的一部分。 Bash 手册中明确指出,当引用 ~
时,不会执行此扩展。
请勿引用
~
。
file=~/path/to/file
如果您需要引用文件名的其余部分:
file=~/"path with spaces/to/file"
(这在普通 shell 中是完全合法的。)
使用
$HOME
代替 ~
。
file="$HOME/path/to/file"
您似乎对 shell 变量的类型有点困惑。
一切都是字符串。
重复直到理解:一切都是字符串。(除了整数,但它们大多是字符串之上的黑客据我所知。还有数组,但它们是字符串的数组。)
这是一个 shell 字符串:
"foo"
。 "42"
也是如此。 42
也是如此。 foo
也是如此。如果你不需要引用某些东西,那么不引用也是合理的;谁想输入"ls" "-la" "some/dir"
?
仍然不那么迷人,但对我有用:
home_folder="/home/$(logname)"
可以从那里工作...
为了补充michaelb958的正确答案,我建议使用模式替换,来自bash的参数扩展(参见
man -P'less +/pattern\ substitution' bash
):
file='~/test.txt'
ls "${file/#~\//$HOME\/}" # This could be double-quoted
/home/user/test.txt
当然这可以用于两种方式:
file="$HOME/test.txt"
echo "${file/#$HOME\//\~\/}"
~/test.txt
sed
过滤输出:为了避免与任何类型的
$HOME
路径发生冲突,我将使用 ;
作为 sed
的 s
命令:
ls -ld ~/* | sed "s;$HOME;~;"
drwxr-xr-x 5 user user 4096 12 jui 16:36 ~/Documents
drwxr-xr-x 5 user user 4096 12 jui 16:36 ~/Desktop
-rw-r--r-- 1 user user 0 10 sep 12:34 ~/test.txt
...
支持“F. Hauri - 放弃 GitHub”, 当自动使用路径作为包含环境变量的字符串时,使用模式替换非常有用,例如。 $HOME。例如,将 KDE dolphin 中的链接转换为包含 URL 的文件,该文件包含指向包含 $HOME 的文本字符串目标。从包含 $HOME 的 dolphin 链接 URL 创建符号链接的脚本失败。我的解决方法是使用模式替换来替换 /home/$USER 环境变量 $HOME。 作为示例,下面的脚本用于创建自定义操作,以将 xfce4 Thunar 中选择的 KDE dolphin 链接更改为符号链接。链接名称只是一个以逗号分隔的目标路径反向列表。 该脚本无法识别 $HOME,因此使用路径替换将其更改为 /home/$USER。
#!/bin/bash
# file: cnv_kde-to-symb_link.sh
# date: 20240404
# desc: Convert a link created in KDE dolphin to a symbolic link
# usge: cnv_kde-to-symb_link.sh %ln
# usge: %ln is the KDE dolphin link
string=`grep URL $1 | sed 's/^.*binder\/\(.*\)$/\1/'`
fstring=`grep URL $1 | sed 's/^.*file:\(.*\)$/\1/'`
fstring="${fstring/#\$HOME\//\/home\/$USER\/}"
#Split the path using "/" into an array of directory names
readarray -d "/" -t array <<< "$string"
# Build the link name by reversing the directory names in the path
lnk="_"
sep=""
element=""
# To evaluate an integer expression use $(($var-int))
cnt=$((${#array[@]}-1))
# for ((i=${#array[@]}-1; i>=0; i--)); do
for ((i=$cnt; i>=0; i--)); do
if [ $i -lt $cnt ]; then sep=","; fi
# Strip leading or trailing spaces, condense multi-space to single space
element=`echo ${array[$i]} | xargs`
lnk=$lnk$sep$element
done
# Create the symbolic link
lstring=$lnk"_ln"
ln -s $fstring ./$lstring