sed / awk - 删除文件名中的 space

sed / awk - remove space in file name

我正在尝试删除文件名中的空格并替换它们。

输入:

echo "File Name1.xml File Name3 report.xml" | sed 's/[[:space:]]/__/g'

然而输出

File__Name1.xml__File__Name3__report.xml

期望的输出

File__Name1.xml File__Name3__report.xml

如果没有描述文件名,这似乎是一个好的开始:

((?:\S.*?)?\.\w{1,})\b

(        // start of captured group
(?:      // non-captured group
\S.*?    // a non-white-space character, then 0 or more any character
)?       // 0 or 1 times
\.       // a dot
\w{1,}   // 1 or more word characters
)        // end of captured group
\b       // a word boundary

您必须查找 PCRE 模式如何转换为 shell 模式。或者它可以是来自 Python/Perl/PHP 脚本的 运行。

Demo

你可以使用 rename:

rename --nows *.xml

这会将当前文件夹中 xml 个文件的所有空格替换为 _

有时它没有 --nows 选项,因此您可以使用搜索和替换:

rename 's/[[:space:]]/__/g' *.xml

如果您只想打印文件名而不编辑名称,最终您可以使用 --dry-run

你在问题的标题中命名为 awk,是吗?

$ echo "File Name1.xml File Name3 report.xml" | \
> awk -F'.xml *' '{for(i=1;i<=NF;i++){gsub(" ","_",$i); printf i<NF?$i ".xml ":"\n" }}'
File_Name1.xml File_Name3_report.xml
$
  • -F'.xml *'指示awk在正则表达式上拆分,请求的扩展加上0个或多个spaces
  • 循环 {for(i=1;i<=NF;i++) 对输入行被分割的所有字段执行 — 请注意,最后一个字段是空的(它是最后一个扩展名之后的内容),但是我们将考虑到这一点...
    循环的 body
    • gsub(" ","_", $i) 将所有出现的 space 替换为当前字段中的下划线,由循环变量 i
    • 索引
    • printf i<NF?$i ".xml ":"\n" 输出不同的东西,如果 i<NF 它是一个常规字段,所以我们附加扩展名和一个 space,否则 i 等于 NF ,我们只想用换行符终止输出行。

它并不完美,它在最后一个文件名后附加了一个 space。我希望这足够好...


▶ A D D E N D U M ◀

我想联系:

为了实现这些目标,我决定将 scriptlet 包装在一个 shell 函数中,将 spaces 更改为下划线的命名为 s2u

$ s2u () { awk -F'\.'' *' -v ext="." '{
> NF--;for(i=1;i<=NF;i++){gsub(" ","_",$i);printf "%s",$i ext (i<NF?" ":"\n")}}'
> }
$ echo "File Name1.xml File Name3 report.xml" | s2u xml
File_Name1.xml File_Name3_report.xml
$

有点不同(更好?)'cs 它不特别打印最后一个字段,而是 special-cases 附加到每个字段的分隔符,但拆分扩展名的想法仍然存在。

假设您问的是如何重命名文件名,而不是删除因其他原因而使用的文件名列表中的空格,这是长而短的方法。漫长的道路使用 sed。简短的方法使用重命名。如果您不是要重命名文件,则您的问题很不清楚,应该修改。

如果目标是简单地获取 xml 文件名列表并使用 sed 更改它们,下面的示例是如何做到这一点。

目录内容:

ls -w 2
bob is over there.xml
fred is here.xml
greg is there.xml

cd [directory with files]
shopt -s nullglob
a_glob=(*.xml);
for ((i=0;i< ${#a_glob[@]}; i++));do 
   echo "${a_glob[i]}";
done
shopt -u nullglob
# output
bob is over there.xml
fred is here.xml
greg is there.xml

# then rename them
cd [directory with files]
shopt -s nullglob
a_glob=(*.xml);
for ((i=0;i< ${#a_glob[@]}; i++));do 
   # I prefer 'rename' for such things
   # rename 's/[[:space:]]/_/g' "${a_glob[i]}";
   # but sed works, can't see any reason to use it for this purpose though
   mv "${a_glob[i]}" $(sed 's/[[:space:]]/_/g' <<< "${a_glob[i]}");
done
shopt -u nullglob

结果:

ls -w 2
bob_is_over_there.xml
fred_is_here.xml
greg_is_there.xml

globbing 是你想要的,因为名称中有空格。

然而,这确实是一个复杂的解决方案,实际上您需要做的只是:

cd [your space containing directory]
rename 's/[[:space:]]/_/g' *.xml

就这样,大功告成。

另一方面,如果您正在尝试创建一个文件名列表,您肯定需要通配方法,如果您只修改语句,它也会执行您想要的操作,也就是说,只是使用 sed 更改输出文件名。

如果您的目标是为了输出而更改文件名,而不是重命名实际文件:

cd [directory with files]
shopt -s nullglob
a_glob=(*.xml);
for ((i=0;i< ${#a_glob[@]}; i++));do 
   echo "${a_glob[i]}" | sed 's/[[:space:]]/_/g';
done
shopt -u nullglob
# output:
bob_is_over_there.xml
fred_is_here.xml
greg_is_there.xml