使用命令行参数更改文件名 Bash



我需要实现一个脚本(duplq.sh(,该脚本将使用命令行参数命名当前目录中存在的所有文本文件。因此,如果执行命令duplq.sh pic 0 3,它将进行以下转换:

pic0.txt必须重命名为pic3.txt

pic1.txt to pic4.txt

pic2.txt to pic5.txt

pic3.txt to pic6.txt

等…

因此,第一个参数始终是文件的名称,第二个参数始终是一个正数。

我还需要确保执行脚本时,第一个重命名(pic0.txt到pic3.txt(不会在当前目录中删除现有的pic3.txt文件。

这是我到目前为止所做的:

 #!/bin/bash
name="$1"
i="$2"
j="$3"

for file in $name*
do
    echo $file
    find /var/log -name 'name[$i]' | sed -e 's/$i/$j/g'
    i=$(($i+1))
    j=$(($j+1))
done 

但是查找命令似乎不起作用。您还有其他解决方案吗?

您要解决的问题实际上有些棘手,我认为您没有完全认为它通过。例如,duplq.sh pic 0 3duplq.sh pic 2 5之间有什么区别 - 看起来两者都应该仅将3添加到数字,或者第二个跳过" pic0.txt"one_answers" pic1.txt"?一个人对名为" pic"," pic.txt"," picture.txt"," picture2.txt"的文件会产生什么影响

到目前为止,脚本中还有很多基本错误:

  • 您应该(几乎(始终将变量引用放在双Qotes中,以避免出乎意料的单词分裂和通配符的扩展。因此,例如,使用echo "$file"代替echo $file。在for file in $name*中,您应该在变量周围(而不是*(进行双重报价,因为您希望将其视为通配符。因此,正确版本是for file in "$name"*

  • 不要将变量引用放在单价中,它们并未扩展。因此,在findsed命令中,您没有传递变量的值,而是传递字面的美元符号,然后是字母。同样,使用双报价。另外,您在"名称"之前没有" $",因此即使在双引号中也不会将其视为变量。

  • 但是findsed命令无论如何都不会做您想做的事情。考虑find /var/log -name "name[1]"-查找名为" name1"的文件,而不是" name1" 一些扩展名。它在当前目录和所有子目录中看起来,我敢肯定您不想要。" 1"("$i"(可能不是当前文件名中的数字。假设有名为" pic0.jpg"," pic0.png"one_answers" pic0.txt"的文件 - 在第一个迭代中,循环可能会找到所有三个图案,诸如" pic0*"之类的模式,然后在第二个和第三次迭代尝试查找不存在的" pic1*"one_answers" pic2*"。另一方面,假设有名为" pic0.txt"," pic5.txt"one_answers" pic8.txt"的文件。同样,它可能会寻找" pic0*"(确定(,然后是" pic1*"(找不到(,然后是" pic2*"(ditto(。

    另外,如果您获得多位数的数字,则模式"名称[10]"将匹配" file0"one_answers" file1",而不是" file10"。我不知道为什么您在那里添加括号,但是他们不做您想要的任何事情。

    您已经在$file变量中一次列出了一个文件,再次使用不同的标准搜索只是添加了混乱。

  • 另外,脚本中的任何时候都不会重命名任何内容。find | sed行将(如果可行( print 文件的新名称,但实际上并未重命名。

    顺便说一句,当您使用mv命令时,请使用mv -nmv -i默默而不可挽回地覆盖文件,如果/当名称发生冲突时。

  • 要防止在增加文件编号时覆盖覆盖,您需要按反向数字顺序进行重命名(即重命名为" pic3.txt"到" pic6.txt" 重命名之前 pic0。txt" to" pic3.txt"(。这尤其棘手,因为如果您只是在"反向"字母 order中对文件名进行排序,那么您将在" pic10.txt"之前获得" pic7.txt"。但是,如果不删除" pic"one_answers" .txt"零件,则不能进行数字排序。

    imo这实际上是解决此脚本正确工作的最棘手的问题。将最大的索引号指定为参数之一,可能是最简单的,并将其始于从中开始,然后倒数为0(通过 numbers 而不是 files。(,然后,对于每个数字,迭代匹配的文件(例如" pic0.jpg"," pic0.png"one_answers" pic0.txt"(。

,所以我认为0 3只是对旧的num and num and num且等效于1 4或100 103的差异的测量。

避免覆盖现有文件,请创建一个新的临时端,将所有受影响的文件移动到其中,然后将所有这些文件移回最后。

#/bin/bash
#
# duplq.sh pic 0 3
base="$1"
delta=$(( $3 - $2 ))
# echo delta $delta
target=$(mktemp -d)
echo $target
# /tmp/tmp.7uXD2GzqAb
add () {
  f="$1"
  b="$2"
  d=$3
  num=${f#./${b}}
  # echo -e "file: $f tnum: $num tnum + d: $((num + d))" ;
  echo -e "$((num + d))" ;
}
for f in $(find -maxdepth 1 -type f -regex ".*/${base}[0-9]+")
do
  newnum=$(add "$f" "${base}" $delta)
  echo mv "$f" "$target/${base}$newnum"
done
# exit
echo mv $target/${base}* .

首先,我尝试仅使用bash语法来检查删除前缀(pic(是否仅剩下数字。我也没有使用Extension .txt-这是读者的练习。从问题不清楚的问题 - 从未明确地告诉所有文件都共享相同的扩展名,但是示例中的所有文件都可以。

使用-regex"。*/$ {base} [0-9] "(,保证值仅是数字。

  num=${f#./${b}}

从file f base(" pic"(中删除。添加了delta d。

我只是回荡了MV命令,而不是真正的移动。

@todo:实现文件名扩展保护。

和其他2个陷阱我想到了:如果您有3个文件PIC0,PIC00和PIC000,它们都将重命名为PIC3。然后,将将PIC08切成图片,然后将08,08将其读取为八进制号(或09或012129等(,并导致错误。

解决此问题的一种方法是,您可以使用" 1"预提取的编号(001或018(,然后添加3,然后删除领先的1:

  001 1001 1004 004
  018 1018 1021 021

但是,这种巧妙的解决方案导致了新问题:

  999 1999 2002 002? 

因此,必须切断领先的1,必须将领先2降低1。但是现在,如果三角洲更大,可以说300:

  018 1018 1318 318 
  918 1918 2218 1218 

好 - 这似乎在起作用。

最新更新