如何在 Linux 中转置部分文件名?

如何在 Linux 中转置部分文件名?

采用可变长度文件名“abcdef - ghijkl.pdf”并将其重命名为“ghijkl - abcdef.pdf”

如何在命令行脚本中为单个文件夹中的所有文件实现这一点?

答案1

由于你使用的是 Ubuntu,你应该至少有一个基于 perl 的renameprename

$ rename -n -- 's/(\w*) - (\w*)/$2 - $1/' *.pdf
rename(abcdef - ghijkl.pdf, ghijkl - abcdef.pdf)

$ prename -n -- 's/(\w*) - (\w*)/$2 - $1/' *.pdf
abcdef - ghijkl.pdf renamed as ghijkl - abcdef.pdf

或者,您可以安装并使用mmv

$ mmv -n '* - *.pdf' '#2 - #1.pdf'
abcdef - ghijkl.pdf -> ghijkl - abcdef.pdf

(在所有情况下,删除-n才能实际完成操作)。

答案2

使用bash:

[[ $f =~ ^([^-]+)\ -\ ([^\.]+)\.(.*) ]] && 
  mv "$f" "${BASH_REMATCH[2]} - ${BASH_REMATCH[1]}.${BASH_REMATCH[3]}"

这使用 bash 的正则表达式测试运算=~符来查看给定的文件名(在 中$f)是否与模式匹配:“除破折号之外的任何内容,后跟空格破折号空格,后跟除句点之外的任何内容,后跟句点,后跟任何内容” 。如果文件名与该模式匹配,则正则表达式括号内的子部分的匹配位将分配给 BASH_REMATCH 数组的元素。

要对特定文件夹中的每个文件执行此操作:

cd /to/that/folder
for f in *
do
  [ -f "$f" ] || continue
  [[ $f =~ ^([^-]+)\ -\ ([^\.]+)\.(.*) ]] && 
    mv "$f" "${BASH_REMATCH[2]} - ${BASH_REMATCH[1]}.${BASH_REMATCH[3]}"
done

仅使用POSIX 指定的变量扩展

pre=${f%%.*}
ext=${f##*.}
mv "$f" "${pre##*- } - ${pre%% -*}.$ext"

答案3

您可以使用该命令创建脚本:

\ls *-*.pdf | sed 's/\(.*\)-\(.*\).pdf/mv \1-\2.pdf \2-\1.pdf/' > script_mv.bash

然后检查脚本是否正确,然后可以执行它:

. ./script_mv.bash

我写了 \ls,因为它取消了 ls 上的选项。

sed 模式的含义是:

  • 找到任何内容1、“-”、任何内容2、“.pdf”。
  • 这两个内容都包含在 ( ) 中,以便它们获得名称 \1 和 \2 。
  • 然后我复制 mv 行,因为 \1 和 \2 ,我可以重新创建文件名。

答案4

害羞的答案,具体到“xxx - yyyy.ddd”名称模式。

find -type f | while read flnm ; do basename "$flnm" | awk -F'[\ .]' '{print $3 " " $2 " " $1 "."$4}'; done

找到一个文件并将名称交给 while read 循环。在那里,使用 basename 提取名称并将其交给 Awk。 awk 使用多个字段分隔符、空格和句点,然后以所需的顺序重新打印字段。

abcdef - ghijkl.pdf

变成

ghijkl - abcdef.pdf

实际应用...将文件重命名为这个新的模式名称

find -type f | while read flnm ; do mv "$(basename "$flnm")"  "$(basename "$flnm" | awk -F'[\ .]' '{print $3 " " $2 " " $1 "."$4}')"; done

唯一的区别是包含 mv 命令并将名称包装为字符串。

相关内容