首页 > 解决方案 > 您如何在多个目录中移动特定文件扩展名的文件,一个目录在各自目录中更深?

问题描述

我希望有人可以帮助我,我正在寻找一个 bash 脚本的帮助,以通过文件扩展名从多个目录移动文件,一个目录在各自目录中更深。

例如,我有一个“项目”目录,其中包含多个目录“项目 001、项目 002、项目 003”等等。我在这些文件夹中有“.JPG”文件,并希望将它们放在各自项目文件夹中的“JPG”文件夹中 - 我将如何使用 bash 脚本来执行此操作,因为手动操作太多了?

为了使事情变得更复杂,其中一些项目文件夹中已经有“JPG”文件夹,其中一些文件夹中已经有一些文件作为重复文件,所以我想我也需要在其中添加一个覆盖确认关于文件名。

我知道一点点 bash,但这有点过头了,所以任何帮助将不胜感激。

谢谢,

/ 哈密

这是在 Ubuntu Server 18.04 LTS 上使用 CLI,在磁盘上包含数千个带有人类文件名的目录 - 空格、括号和各种 unicode 字符,例如日语和欧洲字符。目录的名称多种多样,没有特定的公式。

理想情况下,我想从这个开始:

...对此:

标签: bashcommand-line-interfacesh

解决方案


您可以使用find该搜索器对所有文件和一个由选项调用*.jpg的简单帮助脚本执行所需的操作,以创建目录并将所有文件移动到新目录中。-execfindjpg.jpg

辅助脚本将简单地利用绝对文件名readlink -f,然后使用快速参数扩展从绝对文件名中修剪最后一个/...组件以获得完整路径。然后只需jpg在路径末尾创建目录并将文件移动到新目录即可。

您的辅助脚本(我称之为helper.sh)可能是:

#!/bin/sh

test -z "$1" && exit                        ## validate 1 argument given or exit

full=$(readlink -f "$1")                    ## get full filename
dir="${full%/*}"                            ## get full path

test "${full##*.}" = 'jpg' || exit          ## test extension is jpg or exit

test -z "$dir" && dir="/"                   ## check if file was in / (root) 

test -d "$dir/jpg" || mkdir -p "$dir/jpg"   ## check/create jpg dir at end of path

mv "$full" "$dir/jpg"                       ## move file into new jpg dir

注意:创建帮助脚本后,请确保使用它使其可执行chmod +x helper.sh

原始项目目录树

$ tree Projects/
Projects/
├── Project_001
│   └── Image_001.jpg
├── Project_002
│   ├── Image_002.jpg
│   └── Image_003.jpg
└── Project_003

您在为每个文件调用帮助脚本find的目录上运行的命令将是:Projects

$ find Projects/ -type f -name "*jpg" -exec ./helper.sh '{}' \;

生成的项目目录树

$ tree Projects/
Projects/
├── Project_001
│   └── jpg
│       └── Image_001.jpg
├── Project_002
│   └── jpg
│       ├── Image_002.jpg
│       └── Image_003.jpg
└── Project_003

如果您还有其他问题,请告诉我。

保存已在 jpg 目录中的文件

根据您的附加评论,为了保留项目下目录中.jpg已有的文件jpg,您需要做的就是添加一项额外的检查。如果路径的最后一个组件已经是jpg,只需退出帮助程序,例如

test "${dir##*/}" = 'jpg' && exit           ## if already in jpg dir, exit

在上下文中显示helper.sh

test -z "$1" && exit                        ## validate 1 argument given or exit

full=$(readlink -f "$1")                    ## get full filename
dir="${full%/*}"                            ## get full path (trim last /*)

test "${dir##*/}" = 'jpg' && exit           ## if already in jpg dir, exit
test "${full##*.}" = 'jpg' || exit          ## test extension is jpg or exit
...

原始项目目录树(w/现有 jpg)

$ tree Projects/
Projects/
├── Project_001
│   ├── Image_001.jpg
│   └── jpg
│       └── Image_000.jpg
├── Project_002
│   ├── Image_002.jpg
│   ├── Image_003.jpg
│   └── jpg
│       ├── Image_000.jpg
│       └── Image_001.jpg
└── Project_003

生成的项目目录树

$ tree Projects/
Projects/
├── Project_001
│   └── jpg
│       ├── Image_000.jpg
│       └── Image_001.jpg
├── Project_002
│   └── jpg
│       ├── Image_000.jpg
│       ├── Image_001.jpg
│       ├── Image_002.jpg
│       └── Image_003.jpg
└── Project_003

推荐阅读