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
Strip leading dot from filenames bash script
提问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 find
command you don't need to do all the hard work. You can have find
only match files with a leading dot:
顺便说一句,使用更具选择性的find
命令,您不需要做所有艰苦的工作。您只能拥有find
带前导点的匹配文件:
find files/ -type f -name '.*'
Throwing that all together, then:
把所有这些放在一起,然后:
find files/ -type f -name '.*' -printf '%Pfind 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:
补充说明:
To handle file names with spaces properly you need to quote variable names when you reference them. Write "$file" instead of just
$file
.For extra robustness the
-printf '\0'
andread -d $'\0'
use NUL characters as delimiters so even file names with embedded newlines'\n'
will work.
要正确处理带有空格的文件名,您需要在引用变量名时引用它们。写 "$file" 而不是
$file
.为了获得额外的健壮性,
-printf '\0'
和read -d $'\0'
使用 NUL 字符作为分隔符,因此即使文件名带有嵌入的换行符'\n'
也可以使用。
回答by Arnaud Le Blanc
回答by SiegeX
- This script works with any file you can throw at it, even if they have spaces, newlines or other nefarious characters in their name.
- It works no matter how many subdirectories deep the hidden file is
- Unlike other answers thus far, you
don'thave to change the rest of the script when you change the path
given to
find
- 此脚本适用于您可以扔给它的任何文件,即使它们的名称中有空格、换行符或其他恶意字符。
- 无论隐藏文件有多少个子目录,它都可以工作
- 与迄今为止的其他答案不同,当您更改给定的路径时,您
不必更改脚本的其余部分
find
*Note: I included an echo
so that you can test it like a dry-run. Remove the single echo
if you are satisfied with the results.
*注意:我包含了一个,echo
以便您可以像试运行一样对其进行测试。echo
如果您对结果感到满意,请删除该单曲。