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的好评。

  1. 简化但保留无害的 -- 选项终止符作为良好实践的引导。
  2. 已添加 --no-clobber 以不覆盖现有文件。