Shell 用于将文件夹名称复制并添加到多个子目录中的文件的脚本

Shell script to copy and prepend folder name to files from multiple subdirectories

我有几个共享文件名的不同图片的文件夹,文件夹结构如下:

/parent/folder001/img001.jpg
/parent/folder001/img002.jpg
/parent/folder002/img001.jpg
/parent/folder002/img002.jpg
/parent/folder003/img001.jpg
/parent/folder003/img002.jpg
...

并想copy/rename将这些文件放入一个新文件夹中,如下所示:

/newfolder/folder001_img001.jpg
/newfolder/folder001_img002.jpg
/newfolder/folder002_img001.jpg
/newfolder/folder002_img002.jpg
/newfolder/folder003_img001.jpg
/newfolder/folder003_img002.jpg
...

(如果 newfolder 不是父文件夹的子文件夹可能会更好,因为这最终可能会导致非常奇怪的递归。)

None 个包含图像的文件夹有任何子文件夹。

理想情况下,我希望能够将脚本重新用于 "update" 新文件夹,因为稍后我可能需要添加更多包含图像的文件夹。

如何使用 shell 脚本完成此操作?

我会使用这样的东西:

find -type f -exec sh -c 'f={}; fnew=$(rev <<< "$f" | sed 's~/~_~' | rev); echo "mv $f $fnew"' \;

这会在当前目录结构中查找文件并执行以下操作:

  • 获取文件名
  • 将最后一个 / 替换为 _
  • echo "cp $old_file $new_file"

一旦你有 运行 这个并且看到它打印了正确的命令,删除 echo 以便它有效地执行 mv 命令。

我知道 fnew=$(rev <<< "$f" | sed 's~/~_~' | rev) 有点难看,但我找不到更好的方法将最后一个 / 替换为 _。也许 sed -r 's~/([^/]*)$~_~' 也可以,但我总是喜欢使用 rev :)


由于您的 find-sh c 表达式中表现不佳,让我们为它使用一个 while 循环:

while read -r file
do
    new_file=$(rev <<< "$file" | sed 's~/~_~' | rev)
    echo "mv $file $new_file"; done < <(find . -type f)
done < <(find . -type f)

单线:

while read -r file; do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev); echo "mv $file $new_file"; done < <(find . -type f)

这有点乏味,但可以:

#!/bin/bash
parent=/parent
newfolder=/newfolder
mkdir "$newfolder"
for folder in "$parent"/*; do
  if [[ -d "$folder" ]]; then
    foldername="${folder##*/}"
    for file in "$parent"/"$foldername"/*; do
      filename="${file##*/}"
      newfilename="$foldername"_"$filename"
      cp "$file" "$newfolder"/"$newfilename"
    done
  fi
done

parent 路径放入 parent 变量,将 newfolder 路径放入 newfolder 变量。

救援功能,更新 Jahid 的脚本:

function updateFolder
{
    mkdir ""
    for folder in ""/*; do
    if [[ -d $folder ]]; then
        foldername="${folder##*/}"
        for file in ""/"$foldername"/*; do
            filename="${file##*/}"
            newfilename="$foldername"_"$filename"
            cp "$file" ""/"$newfilename"
        done
    fi
    done
}

用过:

$ updateFolder /parent /newfolder
cd parent  
for i in \*/*;do mv ${i} newfolder/\`dirname ${i}\`_\`basename ${i}\`;done  
mv newfolder \<whereeveryouwant>