从bash脚本的文件名中去除前导点

15

我有一些文件在一堆目录中,它们具有前导点并因此被隐藏。我希望恢复并去掉前导点。

我尝试了以下方法但未成功:

for file in `find files/ -type f`;
do
base=`basename $file`
if [ `$base | cut -c1-2` = "." ];
then newname=`$base | cut -c2-`;
dirs=`dirname $file`;
echo $dirs/$newname;
fi
done

条件语句失败的代码:

[: =: unary operator expected
此外,一些文件名中含有空格,使用file命令返回时它们被分割成了多个部分。
任何帮助都将不胜感激。

当你说“还原”时,你的意思是将文件重命名而不带点吗? - SiegeX
3个回答

35

从变量开头删除内容最简单的方法是使用${var#pattern}

$ FILENAME=.bashrc;    echo "${FILENAME#.}"
bashrc
$ FILENAME=/etc/fstab; echo "${FILENAME#.}"
/etc/fstab

参考bash的手册:

${parameter#word}
${parameter##word}

单词将被扩展为产生一个模式,就像在路径名扩展中一样。如果该模式匹配参数值的开头,则扩展的结果是参数的扩展值,其中最短匹配模式(‘‘#’’情况)或最长匹配模式(‘‘##’’情况)都被删除。

顺便说一下,通过更加选择性的find命令,你无需进行所有的艰苦工作。你可以让find仅匹配以点号开头的文件:

find files/ -type f -name '.*'

综合以上,代码如下:

find files/ -type f -name '.*' -printf '%P\0' |
    while read -d $'\0' path; do
        dir=$(dirname "$path")
        file=$(basename "$path")
        mv "$dir/$file" "$dir/${file#.}"
    done

附加说明:

  1. 为了正确处理文件名中的空格,需要在引用变量时将其用引号括起来。写成 "$file" 而不是仅仅 $file

  2. 为了增强鲁棒性,-printf '\0'read -d $'\0' 使用 NUL 字符作为分隔符,因此即使文件名中嵌入了换行符 '\n' 也可以正常工作。


7
find files/ -name '.*' -printf '%f\n'|while read f; do
        mv "files/$f" "files/${f#.}"
done

1
  1. 此脚本可以处理任何文件,即使它们的名称包含空格、换行符或其他不良字符。
  2. 无论隐藏文件嵌套在多少个子目录中,此脚本都可以正常工作
  3. 与迄今为止其他答案不同,当你更改find命令的路径时,你不需要修改脚本的其余部分。

*注意:我包括了一个echo以便于您测试它是否可以正常运行。如果您对结果满意,请删除单个echo

find . -name '.*' -exec sh -c 'for arg; do d="${arg%/*}"; f=${arg:${#d}}; echo mv "$arg" "$d/${f#.}"; done' _ {} +

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接