【问题标题】:Script to replace/delete characters in direcory and file names (work in progress)用于替换/删除目录和文件名中的字符的脚本(正在进行中)
【发布时间】:2021-07-03 02:47:47
【问题描述】:

我正在尝试从文件名和目录中删除一组字符,例如单引号 (') 和空格。例如,我有:
目录I'm confused,其中包含文件you're right

到目前为止,我已经能够创建一个简短的脚本:

#!/bin/sh
for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done
for f in *; do mv "$f" `echo $f | tr -d \'`; done

按照预期将目录重命名为Im_confused。目录中的文件当然不受影响。

如何替换和删除子目录中的字符?

期待听到您的建议!

【问题讨论】:

  • 你到底卡在哪里了? 1、2 还是 3?
  • 我必须从 1 开始。我只从那个简短的脚本开始,然后调查/阅读如何定义目录深度,但没有找到解决方案。
  • 您的问题并不清楚。我建议您编辑您的问题,以便清楚您在问什么(递归遍历与您对找到的条目实际执行的操作无关)您是否考虑使用find 命令进行递归?跨度>
  • 我冒昧地将您的 bash 标签替换为 shell 标签,因为您的问题与 POSIX shell 相关,而不是 bash。
  • 我的第一个想法是通过使用 posix shell 和我被带到建议这种语法的方向来保持它更加通用。当然,我愿意接受指向其他方式的建议。

标签: bash replace rename filenames script


【解决方案1】:

例如,对于深度 2,命令是:

REP_CHARS=" →" # Characters to replace
DEL_CHARS="'," # Characters to delete
find . -maxdepth 2 | sort -r |
  sed -n -e '/^\.\+$/!{p;s#.\+/#&\n#;p}' |
  sed "n;n;s/[$DEL_CHARS]//g;s/[$REP_CHARS]/_/g" |
  sed "n;N;s/\n//" |
  xargs -L 2 -d '\n' mv 2>/dev/null
  1. find-maxdepth 一起使用。
  2. 使用sort从最深处订购。
  3. 使用sed 仅替换末端部分。
  4. 使用xargs进行mv。
[Original]

├── I'm confused
│   ├── I'm confused
│   │   └── you're right
│   ├── comma, comma
│   └── you're right
└── talking heads-love → building on fire
    └── talking heads-love → building on fire

[After]

├── Im_confused
│   ├── Im_confused
│   │   └── you're right
│   ├── comma_comma
│   └── youre_right
└── talking_heads-love___building_on_fire
    └── talking_heads-love___building_on_fire

【讨论】:

  • 目前我正在尝试清理一些 mp3 专辑。我不想在目录和文件名中包含所有这些字符:逗号、单引号、空格。我什至发现“谈恋爱→着火了”,看到那个箭头......
  • 虽然第二个建议的脚本用于替换和删除恰好 1 个字符,但我想知道如何处理字符列表?我需要添加一个数组吗?我该怎么做?
  • 上例中可以使用字符串指定多个字符。我重写了我的答案,以替换“”和“→”,删除“'”和“,”。指定在正则表达式中被视为特殊字符的字符时要小心。
【解决方案2】:

我会使用这个重命名脚本:

#!/bin/sh
for f in *; do
    g=$(printf '%s' "$f" | tr -s '[:space:]' _ | tr -d "'")
    [ "$f" != "$g" ] && mv -v "$f" "$g"
done

还有这个find 调用

find . -depth -execdir /absolute/path/to/rename.sh '{}' +
  • -depth 深度优先下降到文件层次结构中,因此文件在其父目录之前被重命名
  • -execdir 在找到文件的目录中执行命令,因此$f 的值只包含文件名而不包含其目录。

演示

$ mkdir -p "a b/c d/e f"
$ touch a\ b/c\ d/e\ f/"I'm confused"
$ touch "a file with spaces"
$ tree
.
├── a\ b
│   └── c\ d
│       └── e\ f
│           └── I'm\ confused
├── a\ file\ with\ spaces
└── rename.sh

3 directories, 3 files

$ find . -depth -execdir /tmp/rename.sh '{}' +
renamed 'a b' -> 'a_b'
renamed 'a file with spaces' -> 'a_file_with_spaces'
renamed "I'm confused" -> 'Im_confused'
renamed 'e f' -> 'e_f'
renamed 'c d' -> 'c_d'

$ tree
.
├── a_b
│   └── c_d
│       └── e_f
│           └── Im_confused
├── a_file_with_spaces
└── rename.sh

3 directories, 3 files

【讨论】:

  • 我尝试了你的建议并且它有效。非常感谢!我现在将根据我的需要扩展这个脚本,意思是:我需要替换逗号“;”和文件名中的其他字符...
猜你喜欢
  • 2017-10-19
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多