我正在尝试处理磁盘上许多不同位置的DVD文件。他们的共同点是它们(每组输入文件)都在一个名为$s
的目录中。每种情况下的输出都是为该目录的父级命名的单个文件。
我知道我可以通过以下方式获得每个目录的完全限定路径:
%s
我可以通过管道连接到xargs来获取父目录:
UIImageView
我也知道我可以通过附加:
来自行获取父目录名VIDEO_TS
我无法弄清楚如何将这些参数传递给,例如HandBrakeCLI:
find /Volumes/VolumeName -type d -name "VIDEO_TS" -print0
我已经在这里阅读了关于shell的扩展能力,并怀疑它会在这里提供帮助(不是使用dirname或basename作为开始),但是我读得越多,我就越感到困惑!
答案 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 Find或BashFAQ #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 {} +