如何更改具有相似但不相同结构的所有文件名?

时间:2017-01-21 05:53:46

标签: bash macos shell file command-line

由于各种复杂的照片库迁移必须使用手动复制和重命名文件的导入工具的组合来完成,似乎我收到了大量具有类似结构的文件。这是一个例子:

2009-05-05 - 2009-05-05 - IMG_0486 - 2009-05-05 at 10-13-43 - 4209 - 2009-05-05.JPG

应该是什么:

2009-05-05 - IMG_0486.jpg

其他文件具有相同的结构,但显然各个日期和IMG编号不同。

有什么方法可以在终端中做一些命令行魔术来自动将这些文件重命名为缩短/正确的版本?

3 个答案:

答案 0 :(得分:2)

我假设您可能有子目录,并希望查找此目录树中的所有文件。

这个第一个代码块(你可以把它放在一个脚本中)是“安全的”(什么都不做),但会帮助你看看会做什么。

datep="[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]"
dir="PUT_THE_FULL_PATH_OF_YOUR_MAIN_DIRECTORY"
while IFS= read -r file
do
  name="$(basename "$file")"
  [[ "$name" =~ ^($datep)\ -\ $datep\ -\ ([^[:space:]]+)\ -\ $datep.*[.](.+)$ ]] || continue
  date="${BASH_REMATCH[1]}"
  imgname="${BASH_REMATCH[2]}"
  ext="${BASH_REMATCH[3],,}"
  dir_of_file="$(dirname "$file")"
  target="$dir_of_file/$date - $imgname.$ext"
  echo "$file"
  echo "  would me moved to..."
  echo "    $target"
done < <(find "$dir" -type f)

确保输出符合您的要求。我无法测试你的实际文件,如果这个脚本不能产生完全令人满意的结果,我不会对拔掉头发负任何责任。如果您没有可靠的,经过检查的备份,请不要盲目地让任何人(包括我)通过从互联网上复制和粘贴代码来弄乱您的宝贵数据。

如果您确定,请确定是否要抓住某些人编写的代码而没有任何测试机会,并用echo替换以mv "$file" "$target" 开头的连续三行:

IFS=$'\n'
for file in *
do
printf "mv '$file' '"
printf '%s' $(cut -d" " -f1,4,5 <<< "$file")
printf "'.jpg"
done | sh

请注意,文件名必须与要考虑处理的非常严格的模式匹配,因此如果您注意到某些文件未被处理,则可能需要修改模式。

答案 1 :(得分:1)

假设它们都是完全相同的结构,空格和所有内容,您可以使用awk来分隔名称,使用空格作为断点。这是一个快速而又肮脏的例子:

#!/bin/bash
output=""

for file in /path/to/files/*; do
    unset output #clear variable from previous loop
    output="$(echo $file | awk '{print $1}')" #Assign the first field to the output variable
    output="$output"" - " #Append with [space][dash][space]
    output="$output""$(echo $file | awk '{print $5}')" #Append with IMG_* field
    output="$output""." #Append with period
    #Use -F '.' to split by period, and $NF to grab the last field (to get the extension)
    output="$output""$(echo $file | awk -F '.' '{print $NF}')"
done

从那里,像mv /path/to/files/$file /path/to/files/$output这样的文件循环中的最后一行将重命名该文件。我会先将一些文件复制到另一个文件夹中进行测试,因为我们正在处理文件操作。

所有输出分配行也可以合并为一行,但不易阅读。

output="$(echo $file | awk '{print $1 " - " $5 "."}')""$(echo $file | awk -F '.' '{print $NF}')"

但是你仍然想要一个文件循环。

答案 2 :(得分:1)

假设您要使用第一个日期和IMG *名称转换文件名,您可以在该文件夹上运行以下命令:

stdClass Object ( [PageNumber] => 0 [EntriesPerPage] => 0 [TotalEntries] => 643 [TotalPages] => 0 [Data] => Array ( [0] => stdClass Object ( [OrderId] => 521990a8-365d-43cd-aa6d-e4c54636c3e9 [NumOrderId] => 687215 [GeneralInfo] => stdClass Object ( [Status] => 1 [LabelPrinted] => [LabelError] => [InvoicePrinted] => [PickListPrinted] => [Notes] => 0 [PartShipped] => [Marker] => 0 [ReferenceNum] => C Discount_1701210529XQFC0 [SecondaryReference] => C Discount_1701210529XQFC0 [ExternalReferenceNum] => C Discount_1701210529XQFC0 [ReceivedDate] => 2017-01-21T05:29:26.063 [Source] => CDISCOUNT [SubSource] => C Discount [HoldOrCancel] => [DespatchByDate] => 2017-02-01T06:08:32.603 [Location] => 00000000-0000-0000-0000-000000000000 [NumItems] => 1 ) [ShippingInfo] => stdClass Object ( [Vendor] => DPD [PostalServiceId] => a48ee6be-d857-4c83-880c-47b725430c2c [PostalServiceName] => DPD Expresspak [TotalWeight] => 301 [ItemWeight] => 0 [PackageCategoryId] => 00000000-0000-0000-0000-000000000000 [PackageCategory] => Medium Product [PackageTypeId] => [PackageType] => [PostageCost] => 7.99 [PostageCostExTax] => 0 [TrackingNumber] => [ManualAdjust] => )