[英]Handling special characters in bash script
我不熟悉 bash 脚本。 也许这是一个愚蠢的问题。 但我找不到答案。 我正在研究一个 bash 脚本,它模仿命令ls -sh
的行为,但实际上使用du -sh
来获取文件和文件夹大小。 它对 output 进行排序。 很像du -sh* | sort -h
使用 colors du -sh* | sort -h
。
#!/usr/bin/bash
if [ "$#" = "0" ]
then
du -sh *|awk -f /path/to/color-ls.awk|sort -h
else
du -sh $@|awk -f /path/to/color-ls.awk|sort -h
fi
其中ls-color.awk是:
# color-ls.awk
size=$1;
name=$2;
for (i=3; i<=NF; i++)
{
tmp=(name " " $i);
name=tmp
}
# filename=($0 ~ /'/)? ("\"" name "\""):("'" name "'")
filename=("'" name "'")
printf $1 " "
cmd=("ls -d " filename " --color")
system(cmd)
使用ls --color
为 du -sh 的 output 着色的 awk 脚本
我的脚本适用于大多数文件名,甚至包含空格的文件名。 但它有一些涉及特殊字符的问题,我不知道如何解决。
它正在解释任何包含导致错误的单引号的文件名
sh: 1: Syntax error: Unterminated quoted string
与没有 arguments 的问题相同。 并且它将带有空格的文件名解释为两个名称。
示例:当在名为VirtualBox VMs
的文件夹上使用时,或者在我的主目录中将*
作为参数时,它是 output:
du: cannot access 'VirtualBox': No such file or directory
du: cannot access 'VMs': No such file or directory
我希望脚本跳过特殊字符并将它们按原样传递给du
我尝试在每个文件名之前和之后添加双引号
parse(){
for arg in $@
do
printf "\"$arg\"\n"
done
}
但它似乎没有用。 du 不接受附加到文件名的引号。
du: cannot access '"VirtualBox': No such file or directory
du: cannot access 'VMs"': No such file or directory
此外,用\'
替换引号对以太没有帮助。 也许我只是做错了。
# du -sh $(printf "file'name\n" |sed "s/'/\\\'/g")
du: cannot access 'file\'\''name': No such file or directory
# ls file\'name
"file'name"
空间也是如此
du: cannot access 'VirtualBox\': No such file or directory
du: cannot access 'VMs': No such file or directory
我想让脚本像正常的ls -sh
一样工作,但使用排序的 output 并且在文件夹方面具有更准确的结果。 但是当向它提供 arguments 时,此脚本的工作方式与ls -sh -d
类似。 使lh Desktop
显示 Desktop 的大小,而不是 Desktop 中单个文件和文件夹的大小。 我相信这可以通过一个循环来解决,该循环检查每个参数是文件还是文件夹并相应地执行du -sh
然后排序。
#!/usr/bin/bash
if [ "$#" = "0" ]
then
du -sh *|awk -f /path/to/color-ls.awk|sort -h
else
for i in $@
do
if [[ -d "$i" ]]; then
du -sh $i/* |awk -f /path/to/color-ls.awk
else
du -sh "$i" |awk -f /path/to/color-ls.awk
fi
done|sort -h
fi
但由于某种原因它不起作用
# lh Desktop/
du: cannot access 'Desktop/*': No such file or directory
而使用du -sh Desktop/*
通常适用于交互式 shell。
提前致谢。
由于您没有包含shopt -s nullglob
,因此Desktop/*
很可能没有扩展到任何奇怪的文件,除非那里确实没有文件,您在交互模式下启用了nullglob
,而du -sh
没有实际显示Desktop
中文件的大小。
您也可能在Desktop/
不存在的地方调用脚本。
您可以添加一个打印$PWD
的调试语句。 您也可以尝试使用bash -x
运行脚本。
在您的脚本中,我建议启用nullglob
然后对其进行修改,以便如果目标目录不包含任何文件,则不会调用du -sh
。
就像是:
set -- "$i"/*; [[ $# -gt 0 ]] && du -sh -- "$@" ...
扩展时还应引用$@
。
for i in "$@"; do
这可以简化为for i; do
for i; do
,但我们将修改循环内的位置参数,因此我们展开"$@"
。
您也可以选择将展开的文件存储在数组中。
请不要在一个问题上发表这么多。 请每个问题一个问题。 每个问题一个脚本,等等。
确保使用 shellcheck 检查您的脚本。 它会抓住你的错误。 请参阅https://mywiki.wooledge.org/Quotes 。
- 在没有 arguments 的情况下运行时:
awk 脚本中的filename=("'" name "'")
是一种将带有'
引号的任何内容传递给system()
调用的无效方法,因此正如预期的那样,您会遇到 unterminated '
错误。 修复脚本,或者在 Bash 中更好地重写它,不需要 awk,可能在 Python 或 Z014344AD06FEDA73E。
- 使用 arguments 运行时:
$@
经历了分词和文件名扩展(你应该研究的主题),并将输入的词分词成空格上的词。 使用"$@"
。 引用扩展。
- 我想要的是:
您将使用"$@"
来执行此操作
- 我尝试了什么:
可变内容无关紧要。 你必须改变你使用变量的方式,而不是它的内容。 即使用引号。
- 额外的:
你没有引用扩展。 使用"$i"
而不是$i
。 它是"$i"/*
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.