我需要编写一个实现以下目标的Bash脚本:
1)将最新的pdf文件从文件夹1移至文件夹2;
2)正确处理文件名中可能带有空格的文件;
3)在文本文件中的特定位置输出每个文件名。 (在我的实际用法中,我将使用sed
将文件名放在现有文件的特定位置。)
我试图制作一个文件名数组,然后将它们移动并循环输出文本。但是,以下数组无法处理文件名中带有空格的文件:
pdfs=($(find -name "$DOWNLOADS/*.pdf" -print0 | xargs -0 ls -1 -t | head -n$NUM))
假设文件的名称为“带空格的文件名”。我从上面的数组中获得的内容将在单独的数组条目中包含“ with”和“ Space”。 我不确定如何避免将相同文件名中的这些单词分开对待。 有人可以帮我吗?
谢谢!
-------------更新------------
抱歉,我对第三点含糊不清,因为我认为在实现第一个和第二个目标之后我也许能弄清楚这一点。
基本上,这是一个文本文件,其结尾处以“%comment”开头,并且我需要以“ file = PATH”的格式在该行之前插入文件名。 PATH是我将pdf移至的文件夹2。
答案 0 :(得分:1)
您可以结合使用mapfile
和gnu
的{{1}}版本的find | sort | cut | head
版本来实现此目的,这些版本可以对NUL终止的文件名进行操作:
mapfile -d '' -t pdfs < <(find "$DOWNLOADS/*.pdf" -name 'file*' -printf '%T@:%p\0' |
sort -z -t : -rnk1 | cut -z -d : -f2- | head -z -n $NUM)
使用的命令是:
mapfile -d ''
:使用NUL作为分隔符读取数组find
:以EPOCH +“:” +文件名+ NUL字节的形式输出每个文件的修改标记sort
:在第一个字段上按数字反向排序cut
:从输出中删除第一个字段head
:仅输出前$ NUM个文件名答案 1 :(得分:0)
我想下面的代码将接近您想要的代码:
IFS=$'\n' pdfs=($(find -name "$DOWNLOADS/*.pdf" -print0 | xargs -0 -I ls -lt "{}" | tail -n +1 | head -n$NUM))
然后,您可以通过${pdfs[0]}
,${pdfs[1]}
,...
说明
IFS=$'\n'
仅将以下行用“ \ n”分隔。-I
的xargs
选项告诉xargs将{}
替换为文件名,以便将其引用为"{}"
。tail -n +1
是一种抑制显示“ xargs:'ls'被信号13终止”错误消息的技巧。希望这会有所帮助。
答案 2 :(得分:0)
Bash v4有一个选项globstar
,启用此选项后,我们可以使用**
来匹配零个或多个子目录。
mapfile
是一个内置命令,用于将行读入索引数组变量。 -t
选项删除尾随换行符。
shopt -s globstar
mapfile -t pdffiles < <(ls -t1 **/*.pdf | head -n"$NUM")
typeset -p pdffiles
for f in "${pdffiles[@]}"; do
echo "==="
mv "${f}" /dest/path
sed "/^%comment/i${f}=/dest/path" a-text-file.txt
done
答案 3 :(得分:0)
find downloads -name "*.pdf" -printf "%T@ %p\0" |
sort -z -t' ' -k1 -n |
cut -z -d' ' -f2- |
tail -z -n 3
%T
,格式说明符为@
,这意味着自纪元以来以秒为单位的小数部分,然后打印空间,文件名并用\0
分隔ls
。 ls
用于获得格式良好的输出。您可以执行xargs -0 stat --printf "%Y %n\0"
,这基本上可以使脚本向前移动,因为ls
并不打算用于脚本。只是我无法将stat
的输出分数作为创建日期的一部分。对于第二部分,我们需要将空分界列表保存到文件中
find downloads ........ >"$tmp"
然后:
str='%comment'
{
grep -B$((2**32)) -x "$str" "$out" | grep -v "$str"
# I don't know what you expect to do with newlines in filenames, but I guess you don't have those
cat "$tmp" | sed -z 's/^/file=/' | sed 's/\x0/\n/g'
grep -A$((2**32)) -x "$str" "$out"
} | sponge "$out"
其中output是输出文件名
"$out"
%comment
之前的所有行,并从文件中删除行%comment
本身file=
。我还用零代替了换行符。%comment
之后的所有行,包括%comment
本身pdf=$(...)
。您可以使用mapfile
将其存储到数组中,就像提供其他答案一样。然后移动文件,做类似的事情
<"$tmp" xargs -0 -i mv {} "$outdir"
或更快,只需一步:
{ cat <"$tmp"; printf "%s\0" "$outdir"; } | xargs -0 mv
或者:
<"$tmp" xargs -0 sh -c 'outdir="$1"; shift; mv "$@" "$outdir"' -- "$outdir"
turorialspoint上的实时示例。