我正在使用 bash shell。
您好,脂肪酶 如果有人可以提供某种建议会很高兴,因为谷歌搜索产生了一些答案 但仍然无法使脚本工作。
我是新手使用bash脚本并得到一个脚本来修改,因为它无法复制 处理完文件后,将大量文件从输入目录输入到输出目录。
我们在一个大目录中有一堆pdf。 我们处理一个名为filename.pdf的文件,在处理完一个名为filename.pdf.marker的附加文件后 然后将两个文件filename.pdf.marker和filename.pdf从input / in目录移动到目录output / out。 我们使用大约10-15个文件。
脚本应该执行以下操作:
FILELIST=$(ls ${V04}/*.pdf.marker 2> /dev/null | sort)
for FILEMARKER in ${FILELIST}; do
FILENAME=${V04}/$(basename $FILEMARKER .marker)
mv ${FILENAME} ${VLOGDIR}/.
mv ${FILENAME}.marker ${VLOGDIR}/.
done
因此我需要使用xargs命令。
我设法将.marker文件移到另一行。 现在我需要使用此脚本行移动.pdf文件。
find /input/in -iname "*.marker" -print0 | xargs -0 -r -I {} mv `basename {} .marker` /output/out
我的问题在于:`basename {} .marker` 为什么不从字符串 filename.pdf.marker 中提取字符串 filename.pdf ,并将其替换为 mv 命令?
欢迎任何帮助;)
已更新
答案 0 :(得分:3)
问题是反引号中的命令在调用xargs
之前执行一次。
修复有点困难,尤其是因为你的第2步说'复制',但前面的描述暗示'移动'。我可能会创建一个由xargs
调用的简单脚本:
find /input/in -name '*.marker' -print0 | xargs -0 mover.sh
mover.sh
的内容可能是:
for mrk_source in "$@"
do
pdf_source=$(echo "$mrk_source" | sed 's/\.marker$//')
mrk_target=$(echo "/output/out/$mrk_source" | sed 's%/input/in%%')
pdf_target=$(echo "/output/out/$pdf_source" | sed 's%/input/in%%')
mv "$mrk_source" "$mrk_target"
mv "$pdf_source" "$pdf_target"
done
请注意,此代码保留/input/in
下的任何目录结构,但假定/output/out
下存在相应的目录(不检查)。可以更改代码以展平任何目录结构,或者根据需要创建目录(为读者练习)。在两个xxx_target
赋值行中,文件名操作中有一个小小的手法;我认为它对于相对名称和绝对名称都可以正常工作,但对该部分有点谨慎(换句话说,在使用之前进行测试)。
tripleee评论道:
echo和sed调用非常脆弱 - 例如,某些平台上的echo会将文件名中的反斜杠解释为转义序列。幸运的是,您可以使用shell的替换机制代替
mv "${mrk_source#.marker}" /output/out
。 (当你需要给mv的所有内容都是目标目录时,为什么要计算目标文件名?)
我解释了目标文件名 - 保留子目录,所以/input/in/dir1/abc.pdf转到/output/out/dir1/abc.pdf;如果你想展平目录结构(或者没有目录结构),那么只需指定目的地就足够了。
echo的问题不应该是一个问题,因为回声的原始设计很简单,所有后来的额外......行李只是使得应该完全可靠的东西变得极其不可靠。 也就是说,包含反引号,$(...)等的名称可能存在问题。名称中的反引号或$(...)
没有问题。名称中有反斜杠的问题。
$ mkdir -p input/in output/out
$ for name in a b 'c d' 'e f g' '$(cat x)' '`cat y`' 'a\\nb'
> do
> cp /dev/null input/in/"$name.pdf"
> cp /dev/null "input/in/$name.pdf.marker"
> done
$ ls -lR [io]*
input:
total 0
drwxr-xr-x 16 jleffler staff 544 Aug 22 00:45 in
input/in:
total 0
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 $(cat x).pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 $(cat x).pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 `cat y`.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 `cat y`.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a\\nb.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a\\nb.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 b.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 b.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 c d.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 c d.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 e f g.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 e f g.pdf.marker
output:
total 0
drwxr-xr-x 2 jleffler staff 68 Aug 22 00:45 out
output/out:
$ find input/in -name '*.marker' -print0 | xargs -0 sh mover.sh
mv: rename input/in/a\nb.pdf to ./output/out/a
b.pdf: No such file or directory
$ ls -lR [io]*
input:
total 0
drwxr-xr-x 3 jleffler staff 102 Aug 22 00:46 in
input/in:
total 0
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a\\nb.pdf
output:
total 0
drwxr-xr-x 15 jleffler staff 510 Aug 22 00:46 out
output/out:
total 0
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 $(cat x).pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 $(cat x).pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 `cat y`.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 `cat y`.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 a\nb.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 b.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 b.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 c d.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 c d.pdf.marker
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 e f g.pdf
-rw-r--r-- 1 jleffler staff 0 Aug 22 00:45 e f g.pdf.marker
$
使用Bash内置插件是明智的;我有时会在20世纪80年代陷入困境,需要提醒一下。
for mrk_source in "$@"
do
pdf_source=${mrk_source%.marker}
mrk_target=${mrk_source/\/input\/in/\/output\/out}
pdf_target=${pdf_source/\/input\/in/\/output\/out}
mv "$mrk_source" "$mrk_target"
mv "$pdf_source" "$pdf_target"
done
使用相同的输入文件集,此代码可以干净地运行:
答案 1 :(得分:2)
编辑:正如评论中所指出的,如果文件名中有空格,这将无效。在这种情况下,请参阅@Jonathan Leffler的答案(即使没有空格现在,你也应该使用他的版本,以避免在突然出现空格时发生破坏......)。
由于命令在 之前被扩展,因此无法以这种方式使用它。您将给出xargs
的命令如下所示:
xargs -0 -r -I {} mv {} /output/out
因为它试图从字符串{}中删除任何路径组件和a .marker后缀。
我想说你想在这种情况下使用循环:
for f in $(find /input/in -iname "*.marker"); do
mv `basename $f .marker` /output/out
done
答案 2 :(得分:1)
使用GNU Parallel,您应该可以:
ls "$V04"/*.pdf.marker | parallel -q mv {.} {} "$VLOGDIR"
即使$ V04和$ VLOGDIR包含'“space \ t。
,这也会有效观看介绍视频以了解详情:http://www.youtube.com/watch?v=OpaiGYxkSuQ
答案 3 :(得分:0)
反引号在评估时执行,而不是在xargs运行时执行。也许尝试这样的事情?
find /input/in -iname "*.marker" -print0 |
xargs -r0 -i sh -c 'mv `basename "{}" .marker` /output/out; mv "{}" /output/out'
编辑:shell在这里仍有问题;如果文件名包含双引号,则无法正确解析。使用单独的脚本可能更好:
find /input/in -iname "*.marker" -exec ./myscript {} \;
其中myscript
包含简单的移动命令:
#!/bin/sh
mv `basename "$1" .marker` /output/out
mv "$1" /output/out
答案 4 :(得分:0)
旧脚本的问题是,您尝试捕获一个var中的所有条目,这些条目具有大小限制。 如果不能以这种方式对条目进行排序,则可以解决这个问题:
ls -1 "${V04}/*.pdf,.marker | while read FM;
do
mv "${FM}" "${VLOGDIR}/"
mv "${V04}/$(basename "${FM}" .marker)" "${VLOGDIR}/"
done;