【问题标题】:Create a new sequence of files from an existing sequence, along with numbering从现有序列创建新的文件序列,以及编号
【发布时间】:2012-05-19 18:14:48
【问题描述】:

我知道有人问过这个问题,但我找不到一个以上的解决方案,而且它对我不起作用。本质上,我正在寻找一个 bash 脚本,该脚本将采用如下所示的文件列表:

image1.jpg
image2.jpg
image3.jpg

然后复制每个副本,但按顺序倒序编号。因此,该序列将创建三个新文件,分别是:

image4.jpg
image5.jpg
image6.jpg

然而,image4.jpg 将是 image3.jpg 的未修改副本,而 image5.jpg 将是 image2.jpg 的未修改副本,依此类推。我已经尝试过this stackoverflow question 中列出的解决方案,但没有成功。诚然,我在 bash 脚本路径中的位置不是很远,如果我在第一个列出的答案中获取代码块并制作一个脚本,我总是会一遍又一遍地得到“2:语法错误:”(“意外”。我'我尝试用 ( 改变语法,但没有成功。所以,要么我做错了,要么有更好的脚本。

很抱歉没有早点发布,但我使用的代码是:

image=( image*.jpg )  
MAX=${#image[*]}  
for i in ${image[*]}  
do  
   num=${i:5:3} # grab the digits  
   compliment=$(printf '%03d' $(echo $MAX-$num | bc))  
   ln $i copy_of_image$compliment.jpg  
done

我正在使用此代码并将其粘贴到带有 nano 的文件中,并添加 !#/bin/bash 作为第一行,然后添加 chmod +x script 并通过 sh script 在 bash 中执行。当然,在我的测试运行中,我使用了适当标题为 image1.jpg 的文件 - 但我也想知道如何将此脚本应用于 jpegs 目录,不一定标题为 image(integer).jpg - 在我的文件中保持结构,其中大部分是一个单词,后跟一个数字,然后是 .jpg,并且不必为每次使用都重写脚本。

【问题讨论】:

  • 如果您不发布代码,我们将无法解决语法错误。请做。
  • 感谢更新 数组语法是基础,确保文件顶部有#!/bin/bash,否则你可能会得到sh(甚至csh,在某些平台上)。
  • 仔细阅读,错误为sh script;你想要bash script(或只是./script)。
  • 嘿@triplee,非常感谢您的建议,但我仍然遇到错误。如果我在一个空目录中尝试,在发出touch image1.jpg(再次发出2和3)然后bash script之后,我在第一行得到(standard_in) 1: syntax error的输出,然后ln: creating hard link 'copy_of_image000.jpg': File exists和这些行重复,在脚本顶部有和没有#!/bin/bash。然后,ls 将仅显示 image(interger).jpg 文件和单个 copy_of_image000.jpg。使用./ 具有相同的结果。
  • 看起来您的索引没有正确更新。我没有尝试对这部分代码进行故障排除。

标签: bash rename


【解决方案1】:
  • 也许您的真实测试数据从 001 运行到 300,但这里您有 image1 2 3,因此您从文件名中提取一位,而不是三位。 num=${i:5:1}

  • 无需调用 bc 即可在 bash 中完成整数运算

  • ${#image[@]} 比 ${#image[*]} 更健壮,但在这里应该没有区别。
  • 我没有查字典,但是恭维你女朋友不是什么东西吗?反之亦然,不是吗? :)
  • 另一个命令建立了链接 - 要制作副本,请调用 cp。

代码:

#!/bin/bash
image=( image*.jpg )
MAX=${#image[@]}
for i in ${image[@]}
do
    num=${i:5:1}
    complement=$((2*$MAX-$num+1))
    cp $i image$complement.jpg
done 

最重要的是:如果是 bash,请用 bash 调用它。最好的:做一个shebang(就像你做的那样),使其可执行并通过 ./name 调用它。用 sh 名称调用它会强制错误的解释器。如果您不使其可执行,请将其命名为 bash 名称。

【讨论】:

  • 您为什么不接受命令行参数来说明要处理哪些文件?也许喜欢image=($1*${2-.jpg})
  • @tripleee:因为用户从国外复制了一些脚本,并且自己没有做任何事情来解决问题。他有没有提出计划,如何解决?一步,他哪里有问题要进步?脚本失败了,因为他是从文件名为 bla001.jpg 而不是 bla1.jpg 的页面中获取的。它链接了图像,但没有复制它们。你有没有印象他注意到了这些错误?它是一个编码器?或者这是一个“成为我的免费编码器”的请求?
【解决方案2】:

也许是这样的。它适用于像script image*.jpg 这样的通配符匹配一组文件,这些文件匹配具有相同长度的单调递增数字的常规模式,不太理想的是当前目录中文件的常规子集不那么理想。它只是假设最后一个文件的数字索引加上一个文件名总数是要循环的数字范围。

#!/bin/sh

# Extract number from final file name
eval lastidx=\$$#
tmp=${lastidx#*[!0-9][0-9]}
lastidx=${lastidx#${lastidx%[0-9]$tmp}}
tmp=${lastidx%[0-9][!0-9]*}
lastidx=${lastidx%${lastidx#$tmp[0-9]}}

num=$(expr $lastidx + $#)
width=${#lastidx}

for f; do
    pref=${f%%[0-9]*}
    suff=${f##*[0-9]}
    # Maybe show a warning if pref, suff, or width changed since the previous file
    printf "cp '$f' '$pref%0${width}i$suff'\\n" $num
    num=$(expr $num - 1)
done |
sh

这是sh-兼容的; expr 的东西和前面的子字符串提取很丑陋但与 Bourne 兼容。如果您对 Bash 的内置算术和字符串操作结构感到满意,那么转换为那种形式应该是微不足道的。

(明确地说,${var%foo} 返回 $var 的值,foo 从末尾修剪,${var#foo} 从值的开头进行类似的修剪。常规 shell 通配符匹配运算符在修剪内容的表达式。${#var} 返回 $var 值的长度。)

【讨论】:

  • 这非常有效。我想借此机会承认,正如@userunknown 所提到的,我确实不是一个非常熟练的编码器,但只是一个初学者。如果我以任何方式冒犯了他,我想道歉。我才刚刚开始,非常感谢任何人愿意提供帮助,即使我的意见很少。再次感谢您。
猜你喜欢
  • 1970-01-01
  • 2017-12-17
  • 2021-10-15
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
  • 2018-10-03
相关资源
最近更新 更多