BASH:使用寿命文件名字符不在列表中 - BASH: Raplace filenames characters that are not on list

- 此内容更新于:2015-12-20
主题:

我想创建一个列表,然后迭代槽在文件夹中所有文件,替换文件中的每个角色名称不存在这个列表中下划线。包括空格。但只使用Bash和GNU工具。这有可能吗?

原文:

I want to create a list:

0123456789abcdefghijklmnopqrstuvxwyzABCDEFGHIJKLMNOPQRSTUVXWYZ-._

And then iterate trough all files in folder, replacing every character in the file names that is not present in this list with an underscore _.

That includes blank spaces.

But using Bash and GNU tools only.

Is that possible?

网友:这是相当接近unix.stackexchange.com/a/37398——你可能只是需要正确的正则表达式

(原文:This is pretty close unix.stackexchange.com/a/37398 - you'll probably just need the correct regex)

网友:会发生什么如果你有两个文件在同一文件夹命名和?

(原文:What should happen if you have two files named abc( and abc) in the same folder?)

解决方案:
Bash内部只有:如果包含一个斜杠,您将需要backslash-escape它。
原文:

Bash internals only:

for file in *; do
    repl=${file//[!$permitted]/_}
    case $file in "$repl") continue;; esac  # skip if identical
    # Safety: add a suffix to avoid overwriting
    while [ -e "$repl" ]; do
        repl=${repl}_
    done
    mv "$file" "$repl"
done

If $permitted contains a slash, you will need to backslash-escape it.

网友:值得一提的是,与bash4,递归就放你走了?

(原文:Is it worth mentioning that with bash 4, shopt -s globstar lets you go recursive with for file in **/*; do ?)

网友:这工作很好!-测试它更多了,看看也有例外。

(原文:this worked very well! Goota test it more tought to see if there are exceptions.)

网友:如上Andrea评论,你的风险覆盖文件类似的名字。

(原文:As Andrea commented above, you risk overwriting files with similar names.)

网友:@glennjackman谢谢,对你!我添加了一个粗糙的安全措施。

(原文:@glennjackman Thanks, right you are! I added a crude safety measure.)

解决方案:
有命令的Perl版本,您可以使用:
原文:

Having the Perl version of the rename command, you can use this:

rename 's/[^[:alnum:]._-]/_/g' *
网友:不是一个bash装入的。据我所知,有两种不同的命令,包括在不同版本的Linux。这不是默认安装FreeBSD或OSX。

(原文:rename is not a bash builtin. As far as I can tell, there are two different variations of the command, included in different versions of Linux. It's not installed by default in FreeBSD or OSX.)

网友:@ghoti超过两个。

(原文:@ghoti More than two.)

网友:我不知道这命令。太棒了!

(原文:I was not aware of that rename command. Great!)

网友:这个问题要求“Bash和GNU工具只有“这违反了要求。(不知道为什么你会有这样的要求;GNU工具不是无处不在的如果你争取可移植性;尽管在Linux上,他们是很好的)。

(原文:The question asks for "Bash and GNU tools only" so this violates that requirement. (Not sure why you would have a requirement like that; GNU tools are not ubiquitous either if you strive for portability; although on Linux, they are pretty much a given.))

网友:你有一个糟糕的正则表达式:不要把连字符()括号表达式中——你是包括一系列的人物。perl正则表达式

(原文:You have a bad regex there: don't put a hyphen (-) in the middle of a bracket expression -- you are including a range of characters from Z to .. The perl regex would be /[^\w.-]/)

解决方案:
是的,这是可能的:)
原文:

Yes it is possible :)

for filename in *; do
    newfilename=$(echo "$filename" | sed 's/[^0123456789abcdefghijklmnopqrstuvxwyzABCDEFGHIJKLMNOPQRSTUVXWYZ._-]/_/g')
    mv "$filename" "$newfilename"
done