使用复杂命令查找管道到xargs

时间:2016-01-27 15:30:59

标签: bash

我正在尝试处理磁盘上许多不同位置的DVD文件。他们的共同点是它们(每组输入文件)都在一个名为$s的目录中。每种情况下的输出都是为该目录的父级命名的单个文件。

我知道我可以通过以下方式获得每个目录的完全限定路径:

%s

我可以通过管道连接到xargs来获取父目录:

UIImageView

我也知道我可以通过附加:

来自行获取父目录名
VIDEO_TS

我无法弄清楚如何将这些参数传递给,例如HandBrakeCLI:

find /Volumes/VolumeName -type d -name "VIDEO_TS" -print0

我已经在这里阅读了关于shell的扩展能力,并怀疑它会在这里提供帮助(不是使用dirname或basename作为开始),但是我读得越多,我就越感到困惑!

2 个答案:

答案 0 :(得分:3)

您根本不需要xargs:您可以将NUL分隔的流读入shell循环,并直接从那里运行您想要的命令。

#!/bin/bash

source_dir=/Volumes/VolumeName
dest_dir=/Volumes/OtherName

while IFS= read -r -d '' dir; do
  name=${dir%/VIDEO_TS} # trim /VIDEO_TS off the end of dir, assign to name
  name=${name##*/}      # remove everything before last remaining / from name
  ./HandBrakeCLI -i "$dir" -o "$dest_dir/$name.m4v"
done < <(find "$source_dir" -type d -name "VIDEO_TS" -print0)

请参阅Greg wiki的the article Using FindBashFAQ #001,了解有关在bash中处理输入流的一般信息,或BashFAQ #24了解使用流程替换的价值({ {1}}在这里构造)而不是从查找到循环的管道。

此外,<(...)包含find操作,可按如下方式使用:

-exec

这会直接将参数列表中找到的目录名传递给使用source_dir=/Volumes/VolumeName dest_dir=/Volumes/OtherName export dest_dir # export allows use by subprocesses! find "$source_dir" -type d -name "VIDEO_TS" -exec bash -c ' for dir; do name=${dir%/VIDEO_TS} name=${name##*/} ./HandBrakeCLI -i "$dir" -o "$dest_dir/$name.m4v" done ' _ {} + 调用的shell。由于bash -c循环迭代的默认对象是for,参数列表,这隐式迭代"$@"找到的目录。

答案 1 :(得分:2)

如果我理解你要做什么,最简单的解决方案是创建一个小包装器,它接受一个路径并调用你的CLI:

文件:CLIWrapper

#!/bin/bash
for dir in "$@"; do
  ./HandBrakeCLI -i "${dir%/*}" -o "/path/to/convertedfiles/${dir##*/}.m4v"
done

编辑:我想我误解了这个问题。以上脚本可能应该是:

./HandBrakeCLI -i "$dir" -o "/path/to/convertedfiles/${dir##*/}.m4v"

或者可能略有不同。但这个理论是有效的。 :)

然后,您可以使用-exec选项find来调用该脚本。该脚本循环遍历其参数,使find可以使用+终结符向单个调用发送多个参数:

find /Volumes/VolumeName -type d -name "VIDEO_TS" -exec ./CLIWrapper {} +