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

发布于 2024-10-13 03:38:47 字数 401 浏览 4 评论 0原文

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

我没有成功执行以下操作:

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

此外,某些文件中包含空格,并且文件将它们分开返回。

任何帮助将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

坏尐絯℡ 2024-10-20 03:38:47

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

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

请参阅 bash 手册页:

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

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

顺便说一句,使用更具选择性的 find 命令,您无需完成所有艰苦的工作。您可以查找仅与前导点匹配的文件:

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

将它们放在一起,然后:

find files/ -type f -name '.*' -printf '%P\0' |
    while read -d 

附加说明:

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

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

\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' 将起作用。

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

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

See the bash man page:

${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.

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 files/ -type f -name '.*'

Throwing that all together, then:

find files/ -type f -name '.*' -printf '%P\0' |
    while read -d 

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.

\0' 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.

各自安好 2024-10-20 03:38:47
find files/ -name '.*' -printf '%f\n'|while read f; do
        mv "files/$f" "files/${f#.}"
done
find files/ -name '.*' -printf '%f\n'|while read f; do
        mv "files/$f" "files/${f#.}"
done
行雁书 2024-10-20 03:38:47
  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' _ {} +
  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't have to change the rest of the script when you change the path
    given to 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.

find . -name '.*' -exec sh -c 'for arg; do d="${arg%/*}"; f=${arg:${#d}}; echo mv "$arg" "$d/${f#.}"; done' _ {} +
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文