【问题标题】:Renaming files with double loop?用双循环重命名文件?
【发布时间】:2020-04-24 23:19:30
【问题描述】:

我有以下 28 个文件,我想将它们重命名为

1-1
1-2
...
7-1
7-4

加上正确的文件扩展名。我试过了

for f in *; do
  for i in $(seq 7); do
    for j in $(seq 4); do
      mv $f $i-$j.${f#*.}
     done
   done
done

但这只会重命名第一个文件。

它们的重命名顺序并不重要。

问题

谁能弄清楚如何重命名文件,以便获得$j-$i 命名?

0764342e9a7b64d67b13478443cc6657.png  43fd06b017043443817df07073d76447.png  933441d5176a82b2fdd17fcecb061f76.png
1769998f64f45708ab5660453a76bcd9.png  460c50f9498171d8b3b13415692ba744.png  9638e66b9c7ad1a958a12dcb19918e82.png
1f32eab75790c4ec79dfeeb363381351.jpg  4ba8abdc7e43864ec79d432e9c259ff5.png  9d28f3c61dca4daaecc7f257b4ee09be.jpg
237b4de6ee17bb5033d7b17660ceef75.png  5b09795f9eef920da1207b2549cd5d80.png  c1d0c1520d62a811f9de297eecc08235.png
288ac636a508b903ef1d5c8c914a531c.png  60eff92e2dcf2192449c47fdb94551a1.jpg  e2080072a8615f3016046f396ccba40f.png
2aeddcc1c52b32d81331c4be957bbfa4.png  6960cdb5cc9951e96f4a95aba44f9377.jpg  e2d25004b63c60f83b690d3394277d4d.jpg
2b9f5508623ef64f8f0e81ae6bb1fb24.png  6ab9951011bad2bed060658ac58ea7c1.png  e6989ec43b8fcab262b6a414313b6538.png
36f4a71039adaffdd3e173ab302e5142.png  6b0f52f96bce76c004be0a3d70e2ef3f.png  e8e7f53b39b632427333d700f34b2c5b.png
392da2e9809cca9d9357b3d1f4868de1.jpg  6c8a9665ee8a3e251bad53748815cedd.png
3e7bfa5919f5d49d3dfc27574f346337.png  8fd5ec47f3d31844be60c1350361905e.jpg

【问题讨论】:

  • 那么,在每次迭代中,您都试图移动同一个文件?你没有收到任何错误吗?
  • 不,每个文件只能重读一次。

标签: linux bash


【解决方案1】:

您可以创建一个包含新前缀的数组,然后遍历文件名并获取相应的数组元素。

# the convoluted way to create the array (don't use it, see below)
fnames=()
for i in {1..7}; do
  for j in {1..4}; do
     fnames+=("$i-$j")
  done
done

# the short way using two brace expansions, credits go to @Benjamin W.
fnames=({1..7}-{1..4})

idx=0
for f in *; do
  mv "$f" "${fnames[idx++]}.${f#*.}"
done

【讨论】:

  • @Freddy 你能解释一下${f#*.} 是如何打印文件扩展名的吗?
  • @TheRockSays ${f#*.} 从文件名中删除模式*. 的最短前缀,即任何后跟. 的字符。如果您有一个文件名foo.txt,它将从名称中删除foo.。但是如果你有foo.bar.txt,那么这只会删除foo.。在这种情况下,您需要${f##*.} 来删除模式的最长 前缀以获得后缀txt。见Shell Parameter Expansion
【解决方案2】:

创建两个伪文件,将它们粘贴在一起并使用 sed 将每一行变成一个命令:

paste <(printf '%s\n' *) <(printf '%s\n' {1..7}-{1..4}) \
    | sed 's/^/mv /;s/\(\....\)\(.*\)/\1\2\1/' \
    | bash

paste 命令的输出类似于

$ paste <(printf '%s\n' *) <(printf '%s\n' {1..7}-{1..4})
0764342e9a7b64d67b13478443cc6657.png    1-1
1769998f64f45708ab5660453a76bcd9.png    1-2
1f32eab75790c4ec79dfeeb363381351.jpg    1-3
237b4de6ee17bb5033d7b17660ceef75.png    1-4
288ac636a508b903ef1d5c8c914a531c.png    2-1
2aeddcc1c52b32d81331c4be957bbfa4.png    2-2
2b9f5508623ef64f8f0e81ae6bb1fb24.png    2-3
36f4a71039adaffdd3e173ab302e5142.png    2-4
392da2e9809cca9d9357b3d1f4868de1.jpg    3-1
3e7bfa5919f5d49d3dfc27574f346337.png    3-2
<snip>

等等; sed 把它变成了

mv 0764342e9a7b64d67b13478443cc6657.png 1-1.png
mv 1769998f64f45708ab5660453a76bcd9.png 1-2.png
mv 1f32eab75790c4ec79dfeeb363381351.jpg 1-3.jpg
mv 237b4de6ee17bb5033d7b17660ceef75.png 1-4.png
mv 288ac636a508b903ef1d5c8c914a531c.png 2-1.png
mv 2aeddcc1c52b32d81331c4be957bbfa4.png 2-2.png
mv 2b9f5508623ef64f8f0e81ae6bb1fb24.png 2-3.png
mv 36f4a71039adaffdd3e173ab302e5142.png 2-4.png
mv 392da2e9809cca9d9357b3d1f4868de1.jpg 3-1.jpg
mv 3e7bfa5919f5d49d3dfc27574f346337.png 3-2.png
<snip>

然后通过管道连接到 bash 运行它。

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2012-02-12
    • 1970-01-01
    相关资源
    最近更新 更多