Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex BASH:Raplace文件名不在列表中的字符_Regex_Bash_Filenames - Fatal编程技术网

Regex BASH:Raplace文件名不在列表中的字符

Regex BASH:Raplace文件名不在列表中的字符,regex,bash,filenames,Regex,Bash,Filenames,我想创建一个列表: 0123456789abcdefghijklmnopqrstuvxwyzABCDEFGHIJKLMNOPQRSTUVXWYZ-._ 然后遍历文件夹中的所有文件,将列表中不存在的文件名中的每个字符替换为下划线。 这包括空格 但是只使用Bash和GNU工具 有可能吗?是的,有可能:) 使用Perl版本的rename命令,您可以使用: rename 's/[^[:alnum:]._-]/_/g' * 仅限Bash内部构件: for file in *; do repl=

我想创建一个列表:

0123456789abcdefghijklmnopqrstuvxwyzABCDEFGHIJKLMNOPQRSTUVXWYZ-._
然后遍历文件夹中的所有文件,将列表中不存在的文件名中的每个字符替换为下划线

这包括空格

但是只使用Bash和GNU工具

有可能吗?

是的,有可能:)


使用Perl版本的
rename
命令,您可以使用:

rename 's/[^[:alnum:]._-]/_/g' *
仅限Bash内部构件:

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

如果
$allowed
包含斜杠,则需要对其进行反斜杠转义。

这非常接近-您可能只需要正确的regex如果在同一文件夹中有两个名为
abc(
abc)
的文件,
重命名
不是bash内置的。据我所知,该命令有两种不同的变体,包含在不同版本的Linux中。默认情况下,它不是在FreeBSD或OSX中安装的。@ghoti不止两个。@ghoti我从来没有说过它是bash内置的,至少在Debian上是Perl脚本。但是,是的,该命令在不同的系统上有不同的版本,具有不同的功能集。问题是“仅限Bash和GNU工具”,因此这违反了该要求。(不确定你为什么会有这样的要求;如果你努力实现可移植性,GNU工具也不是无处不在的;尽管在Linux上,它们几乎是给定的。)你有一个糟糕的正则表达式:不要放连字符(
-
)在一个括号表达式的中间,你可以从一个代码中包含一系列字符,从代码> z <代码>到<代码> .<代码>。perl正则表达式应该是
/[^\w.-]/
值得一提的是,在Bash4中,
shopt-s globstar
允许对**/*中的文件使用
进行递归;是否执行
?此操作非常有效!Goota更仔细地测试一下,看看是否有异常。正如Andrea在上面评论的那样,您有可能覆盖具有类似名称的文件。@glennjackman谢谢,您说得对!我添加了一个粗略的安全措施。如何修改它以使其与find一起工作?(保持路径/文件夹名称不变,仅清理文件名)
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