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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4763041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:34:56  来源:igfitidea点击:

Strip leading dot from filenames bash script

linuxbashfind

提问by Radek

I have some files in a bunch of directories that have a leading dot and thus are hidden. I would like to revert that and strip the leading dot.

我在一堆目录中有一些文件,这些文件有一个前导点,因此被隐藏了。我想恢复它并去除前导点。

I was unsuccessful with the following:

我在以下方面没有成功:

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

Which fails on the condition statement:

在条件语句上失败:

[: =: unary operator expected

Furthermore, some files have a space in them and file returns them split.

此外,某些文件中有空格,文件将它们拆分返回。

Any help would be appreciated.

任何帮助,将不胜感激。

采纳答案by John Kugelman

The easiest way to delete something from the start of a variable is to use ${var#pattern}.

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

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

See the bash man page:

请参阅 bash 手册页:

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

The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ‘‘#'' case) or the longest matching pattern (the ‘‘##'' case) deleted.

${参数#word}
${参数##word}

这个词被扩展以产生一个模式,就像在路径名扩展中一样。如果模式匹配参数值的开头,则扩展的结果是具有最短匹配模式(“#”大小写)或最长匹配模式(“##”)的参数的扩展值'案例)删除。

By the way, with a more selective findcommand you don't need to do all the hard work. You can have findonly match files with a leading dot:

顺便说一句,使用更具选择性的find命令,您不需要做所有艰苦的工作。您只能拥有find带前导点的匹配文件:

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

Throwing that all together, then:

把所有这些放在一起,然后:

find files/ -type f -name '.*' -printf '%P
find files/ -name '.*' -printf '%f\n'|while read f; do
        mv "files/$f" "files/${f#.}"
done
' | while read -d $'
find . -name '.*' -exec sh -c 'for arg; do d="${arg%/*}"; f=${arg:${#d}}; echo mv "$arg" "$d/${f#.}"; done' _ {} +
' path; do dir=$(dirname "$path") file=$(basename "$path") mv "$dir/$file" "$dir/${file#.}" done

Additional notes:

补充说明:

  1. To handle file names with spaces properly you need to quote variable names when you reference them. Write "$file" instead of just $file.

  2. For extra robustness the -printf '\0'and read -d $'\0'use NUL characters as delimiters so even file names with embedded newlines '\n'will work.

  1. 要正确处理带有空格的文件名,您需要在引用变量名时引用它们。写 "$file" 而不是$file.

  2. 为了获得额外的健壮性,-printf '\0'read -d $'\0'使用 NUL 字符作为分隔符,因此即使文件名带有嵌入的换行符'\n'也可以使用。

回答by Arnaud Le Blanc

##代码##

回答by SiegeX

  1. This script works with any file you can throw at it, even if they have spaces, newlines or other nefarious characters in their name.
  2. It works no matter how many subdirectories deep the hidden file is
  3. Unlike other answers thus far, you don'thave to change the rest of the script when you change the path given to find
  1. 此脚本适用于您可以扔给它的任何文件,即使它们的名称中有空格、换行符或其他恶意字符。
  2. 无论隐藏文件有多少个子目录,它都可以工作
  3. 与迄今为止的其他答案不同,当您更改给定的路径时,您 不必更改脚本的其余部分find

*Note: I included an echoso that you can test it like a dry-run. Remove the single echoif you are satisfied with the results.

*注意:我包含了一个,echo以便您可以像试运行一样对其进行测试。echo如果您对结果感到满意,请删除该单曲。

##代码##