Bash 隐藏文件的功能有问题
Bash problem with function that hides files
我有这个功能
function hide {
for f in "$@"; do
if [[ ! ${f::1} == '.' ]]; then
mv $f .$f
fi
done
}
应该隐藏作为输入传递的文件,如果它尚未隐藏的话。
当我在名称包含空格的文件上使用它时,例如:
touch "ciao ciao"
hide ciao\ ciao
它不起作用,我收到了这个错误:
usage: mv [-f | -i | -n] [-v] source target
mv [-f | -i | -n] [-v] source ... directory
我尝试在 mv 命令中将 .$f
更改为 ."$f"
,但仍然出现错误。
根据@Jetchisel,您需要在将参数传递给 mv
时引用变量以确保保留空格:
function hide {
for f in "$@"; do
if [[ ! ${f::1} == '.' ]]; then
mv "$f" ".$f" # <= note variable references are quoted
fi
done
}
改进@rtx13 的回答:
- 安全处理完整路径
- 优先使用 POSIX 语法而不是 Bash 细节。
#!/usr/bin/env sh
hide ()
{
# Without in, for loop iterates arguments
for path; do
# Strips-out the leading directory path to keep file name only
file="${path##*/}"
# If file name starts with a dot, continue to next argument
[ -n "${file##.*}" ] || continue
# Strips out the trailing file name to keep the leading directory path only
base="${path%/*}"
# If base is same as file, then there is no leading dir, so prepend current
if [ "$base" = "$file" ]; then
base='.'
path="./$path"
fi
# Performs the file rename
mv --no-clobber -- "$path" "$base/.$file" # Always double quote variables expansion
done
}
编辑:
正在关注gniourf_gniourf的好评。
- 简化但保留无害的
--
选项终止符作为良好实践的引导。
- 已添加
--no-clobber
以不覆盖现有文件。
我有这个功能
function hide {
for f in "$@"; do
if [[ ! ${f::1} == '.' ]]; then
mv $f .$f
fi
done
}
应该隐藏作为输入传递的文件,如果它尚未隐藏的话。
当我在名称包含空格的文件上使用它时,例如:
touch "ciao ciao"
hide ciao\ ciao
它不起作用,我收到了这个错误:
usage: mv [-f | -i | -n] [-v] source target
mv [-f | -i | -n] [-v] source ... directory
我尝试在 mv 命令中将 .$f
更改为 ."$f"
,但仍然出现错误。
根据@Jetchisel,您需要在将参数传递给 mv
时引用变量以确保保留空格:
function hide {
for f in "$@"; do
if [[ ! ${f::1} == '.' ]]; then
mv "$f" ".$f" # <= note variable references are quoted
fi
done
}
改进@rtx13 的回答:
- 安全处理完整路径
- 优先使用 POSIX 语法而不是 Bash 细节。
#!/usr/bin/env sh
hide ()
{
# Without in, for loop iterates arguments
for path; do
# Strips-out the leading directory path to keep file name only
file="${path##*/}"
# If file name starts with a dot, continue to next argument
[ -n "${file##.*}" ] || continue
# Strips out the trailing file name to keep the leading directory path only
base="${path%/*}"
# If base is same as file, then there is no leading dir, so prepend current
if [ "$base" = "$file" ]; then
base='.'
path="./$path"
fi
# Performs the file rename
mv --no-clobber -- "$path" "$base/.$file" # Always double quote variables expansion
done
}
编辑:
正在关注gniourf_gniourf的好评。
- 简化但保留无害的
--
选项终止符作为良好实践的引导。 - 已添加
--no-clobber
以不覆盖现有文件。