首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不知道文件路径的情况下对随机命名文件进行大量重命名

在不知道文件路径的情况下对随机命名文件进行大量重命名
EN

Stack Overflow用户
提问于 2016-04-26 09:34:24
回答 3查看 242关注 0票数 0

在路径中对文件进行大规模重命名时出现问题。

这是我的问题:我有一个大约16000或更多的文件驱动器(所有的图像,但可能是.psd,.jpg,.ai,.png等)散落在一个非常混乱的方式,但文件名是唯一的,但由于数量巨大,我不能肯定(我的意思是,可能有2个文件名为abc.ai或类似的,但不多)。我不知道路径,因为csv只包含原始文件名,以及它们应该重命名为什么。

基本上,csv的第一行是这样的:

qwerty.jpg,asdfg.jpg

123-ASDqwe.ai,abcfgd.ai.

我确实尝试了我找到的几个解决方案;sed,一些脚本,任何我能尝试的东西,我都做了。

我真的很想听你的建议或想法,甚至是一个解决方案!

注意:我试过:

代码语言:javascript
复制
sed 's/"//g' names.csv | while IFS=, read orig new; do echo mv "$orig" "$new"; done

代码语言:javascript
复制
sed 's/^/mv -i -v "/;s/, /" "/;s/$/";/' < names.csv | bash -

代码语言:javascript
复制
#!/bin/bash
 while read line          
 do          
      OldImageName=${line%,*}
      NewImageName=${line#*,}
      mv "$OldImageName" "$NewImageName"
 done <"names.csv"
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-19 12:49:16

这是在上面描述的特定情况下工作的完整解决方案--它考虑了重复的文件(在不同的文件夹中),并且文件名的命名(空格、重音等)也不影响脚本。见下文的解决办法:

代码语言:javascript
复制
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

while read line
do
  OldImageName=$(echo $line | cut -d "," -f 1) 
  NewImageName=$(echo $line | cut -d "," -f 2)

  isMatchRelativePath=$(echo $(find . -name "$OldImageName"));
  isMatchNewName=$(echo $(find . -name "$NewImageName"));

  if [ ! -z "$isMatchRelativePath" ];
  then

      find . -name "$OldImageName" -print0 | while read -d $'\0' file
        do

        relativeFolder="${file%$OldImageName}"

        quote1="$relativeFolder$OldImageName";
        quote2="$relativeFolder$NewImageName";

        mv "${quote1}" "${quote2}"
        echo "$relativeFolder$OldImageName, $relativeFolder$NewImageName">>"$DIR/success.csv"
      done


  elif [ ! -z "$isMatchNewName" ]; then
       echo "alreadyRenamed"
      echo "$relativeFolder$OldImageName, $relativeFolder$NewImageName">>"$DIR/alreadyRenamed.csv"
  else
      echo "failed"
      echo "$relativeFolder$OldImageName, $relativeFolder$NewImageName">>"$DIR/failed.csv"
  fi

done <input.csv
票数 0
EN

Stack Overflow用户

发布于 2016-04-26 09:55:10

如果您完全确定names.txt将以顺序oldname,newname的方式命名,那么下面的逻辑就足够了:

代码语言:javascript
复制
#!/bin/bash

 while read line
 do
      # Splitting the line with delimiter as ',' and 
      # getting the fields before and after

      OldImageName=$(echo $line | cut -d "," -f 1) 
      NewImageName=$(echo $line | cut -d "," -f 2)

      if [ $(find . -name "$OldImageName" | wc -l) -gt 0 ]; then

          # Get the absolute path of the file

          path=$(dirname $(readlink -f "$OldImageName"))

          # Verbose option '-v' for verifying the file rename and 
          # to suppress errors if file not present

          mv -v "$path/$OldImageName" "$path/$NewImageName" 2>/dev/null 
      fi

 done <names.csv
票数 2
EN

Stack Overflow用户

发布于 2016-04-26 10:29:58

(在评论中澄清了问题后重写了答案)。

第一种解决方案只有在CSV包含整个路径时才能工作,而不仅仅是basenames。您需要遍历它,查找每个文件并重命名它。

代码语言:javascript
复制
sed -r 's/, ?/\t/' names.csv | while IFS=$'\t' read orig new; do 
   find $DIR -type f -name "$orig" | while read path; do
      dirname=`dirname "$path"`
      target_path="$dirname/$new"
      if [[ ! -f "$target_path"]]; then
         mv -v -- "$path" "$target_path"
      else 
         echo "Could not rename '$path' to '$target_path'. Target file exists" >&2 
      fi 
   done
done

$DIR替换为最上面的目录.注意:我假设每个basename可能对应于不同目录中的许多文件。这就是我迭代find输出的原因。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36860923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档