bash - 您如何在多个目录中移动特定文件扩展名的文件,一个目录在各自目录中更深?
问题描述
我希望有人可以帮助我,我正在寻找一个 bash 脚本的帮助,以通过文件扩展名从多个目录移动文件,一个目录在各自目录中更深。
例如,我有一个“项目”目录,其中包含多个目录“项目 001、项目 002、项目 003”等等。我在这些文件夹中有“.JPG”文件,并希望将它们放在各自项目文件夹中的“JPG”文件夹中 - 我将如何使用 bash 脚本来执行此操作,因为手动操作太多了?
为了使事情变得更复杂,其中一些项目文件夹中已经有“JPG”文件夹,其中一些文件夹中已经有一些文件作为重复文件,所以我想我也需要在其中添加一个覆盖确认关于文件名。
我知道一点点 bash,但这有点过头了,所以任何帮助将不胜感激。
谢谢,
/ 哈密
这是在 Ubuntu Server 18.04 LTS 上使用 CLI,在磁盘上包含数千个带有人类文件名的目录 - 空格、括号和各种 unicode 字符,例如日语和欧洲字符。目录的名称多种多样,没有特定的公式。
理想情况下,我想从这个开始:
- 项目
- 001计划
- 图片 001.jpg
- 002项目
- 图片 002.jpg
- 图片 003.jpg
- 003项目
- 001计划
...对此:
- 项目
- 001计划
- JPG
- 图片 001.jpg
- JPG
- 002项目
- JPG
- 图片 002.jpg
- 图片 003.jpg
- JPG
- 003项目
- 001计划
解决方案
您可以使用find
该搜索器对所有文件和一个由选项调用*.jpg
的简单帮助脚本执行所需的操作,以创建目录并将所有文件移动到新目录中。-exec
find
jpg
.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
推荐阅读
- android - 如何在Android中制作不会自行折叠的通知?
- c++ - 求两个整数之间的偶校验数个数
- r - 使用 clusterMixType 的每个集群的轮廓值
- swift - PKToolPicker 添加文本、形状和签名
- linux - 如何即时更改 KVM 的网络设置?
- java - 如何在 ImageJ/FiJiplugin uiService.show(BufferedImage) 中显示缓冲图像或浮点数组图像
- php - Wordpress WP_Query $args,显示已发布的帖子和当前用户的待处理帖子
- swift - 在“theMove *”类型的对象上找不到属性“move”
- android - 方向切换后播放声音文件 [Android Studio]
- php - 从 WooCommerce 中的订单中获取最后一个产品