Bash 查找、xargs:为每个文件执行命令链
我很抱歉,如果问题的标题不够详细。请随意推荐更好的变体 我要执行以下任务: 在一个目录中,我有许多JPEG格式的照片文件。我想从EXIF中提取这些照片拍摄的日期,为每个日期创建一个新目录,并将文件移动到相关目录 (如果日期和时间的格式为Bash 查找、xargs:为每个文件执行命令链,bash,shell,find,pipe,xargs,Bash,Shell,Find,Pipe,Xargs,我很抱歉,如果问题的标题不够详细。请随意推荐更好的变体 我要执行以下任务: 在一个目录中,我有许多JPEG格式的照片文件。我想从EXIF中提取这些照片拍摄的日期,为每个日期创建一个新目录,并将文件移动到相关目录 (如果日期和时间的格式为YYYY:MM:DD hh:MM:ss,我希望目录名的格式为yyy-MM-DD,这就是我使用sed的原因) 我知道如何分别执行这些任务,但未能将它们组合在一起。我花了一些时间研究如何使用find和-exec或xargs执行命令,但仍然无法理解如何正确地链接所有内容
YYYY:MM:DD hh:MM:ss
,我希望目录名的格式为yyy-MM-DD
,这就是我使用sed的原因)
我知道如何分别执行这些任务,但未能将它们组合在一起。我花了一些时间研究如何使用find
和-exec
或xargs
执行命令,但仍然无法理解如何正确地链接所有内容
最后,我使用两个命令完成了任务:
find . -name '*.jpg' -exec sh -c "identify -format %[exif:DateTimeOriginal] {}
| sed 's/ [0-9:]*//; s/:/-/g' | xargs mkdir -p" \;
find . -name '*.jpg' -exec sh -c "identify -format %[exif:DateTimeOriginal] {}
| sed 's/ [0-9:]*//; s/:/-/g; s/$/\//' | xargs mv {}" \;
但是我不喜欢复制,我也不喜欢
-exec sh-c
。有没有正确的方法可以在一行中完成此操作,而不使用-exec sh-c
更好的解决方案是将逻辑放入脚本中,使其易于执行和测试,而不是只关注一行程序。将其放入名为movetodate.sh的文件中
:
#!/usr/bin/env bash
# This script takes one or more image file paths
set -e
set -o pipefail
for path in "$@"; do
date=$(identify -format %[exif:DateTimeOriginal] | sed 's/ [0-9:]*//; s/:/-/g')
dest=$(dirname "$path")/$date
mkdir -p "$dest"
mv "$path" "$dest"
done
然后,要调用它:
find . -name '*.jpg' -exec ./movetodate.sh {} +
这很容易做到:
为此:
.
├── 2012-08-07
│ └── b.jpg
└── 2013-10-17
└── a.jpg
如果仍要使用标识
,可以按如下方式重写命令:
script=$(cat <<'SCRIPT'
d=$(
d=$(identify -format "%[exif:DateTimeOriginal]" "$0" 2>/dev/null) || exit $?
d=${d:0:10}
printf '%s/%s' "$(dirname "$0")" "${d//:/-}"
) || exit $?
mkdir -p "$d" && mv -v "$0" "$d"
SCRIPT
)
find "$dir" -name '*.jpg' -exec bash -c "$script" {} \;
script=$(cat使用parallel,您不需要脚本,而是需要:
doit() {
path="$1"
date=$(identify -format %[exif:DateTimeOriginal] | sed 's/ [0-9:]*//; s/:/-/g')
dest=$(dirname "$path")/$date
mkdir -p "$dest"
mv "$path" "$dest"
}
export -f doit
find . -name '*.jpg' | parallel doit
script=$(cat <<'SCRIPT'
d=$(
d=$(identify -format "%[exif:DateTimeOriginal]" "$0" 2>/dev/null) || exit $?
d=${d:0:10}
printf '%s/%s' "$(dirname "$0")" "${d//:/-}"
) || exit $?
mkdir -p "$d" && mv -v "$0" "$d"
SCRIPT
)
find "$dir" -name '*.jpg' -exec bash -c "$script" {} \;
doit() {
path="$1"
date=$(identify -format %[exif:DateTimeOriginal] | sed 's/ [0-9:]*//; s/:/-/g')
dest=$(dirname "$path")/$date
mkdir -p "$dest"
mv "$path" "$dest"
}
export -f doit
find . -name '*.jpg' | parallel doit