Bash 查找、xargs:为每个文件执行命令链

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执行命令,但仍然无法理解如何正确地链接所有内容

我很抱歉,如果问题的标题不够详细。请随意推荐更好的变体

我要执行以下任务: 在一个目录中,我有许多JPEG格式的照片文件。我想从EXIF中提取这些照片拍摄的日期,为每个日期创建一个新目录,并将文件移动到相关目录

(如果日期和时间的格式为
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