我有以下命令:
files=$(ls -lhrt dirname) && echo $files | head -5 && echo $files | tail -5
我们的想法是在目录dirname
中返回最旧和最新的5个文件。这将返回请求的数据 - 但是,这些行混杂在一起。
有没有办法更好地格式化输出? (或者也许是编写此功能的更好方法)?
答案 0 :(得分:2)
始终引用变量扩展以防止单词拆分和通配。当你离开$files
不带引号的bash时,单词拆分传递会导致换行丢失。
files=$(ls -lhrt dirname) && echo "$files" | head -5 && echo "$files" | tail -5
使用&&
运算符没有任何实际好处。我只想写:
files=$(ls -lhrt dirname)
echo "$files" | head -5
echo "$files" | tail -5
或者,更好的是,将echo
交换为<<<
以避免不必要的子流程。
files=$(ls -lhrt dirname)
head -5 <<< "$files"
tail -5 <<< "$files"
答案 1 :(得分:2)
(无需将前一个命令的整个输出存储到一个变量中)
Nota:沿着这个,我将使用前4行和最后4行使用seq 1 100..
进行采样,但使用ls -lhrt dirname
进行采样的前5行和后5行。
head
和tail
如果您尝试:
seq 1 100000 | (head -n 4;tail -n 4;)
1
2
3
4
99997
99998
99999
100000
似乎可以胜任,但
seq 1 1000 | (head -n 4;tail -n 4;)
1
2
3
4
给出错误答案。
这是由于缓冲,但是bash允许您使用无缓冲的输入:
seq 1 12 | { for i in {1..4};do read foo;echo "$foo";done;tail -n 4 ;}
1
2
3
4
9
10
11
12
根据您的要求,试试这个:
{ for i in {1..5};do read foo;echo "$foo";done;tail -n 5;} < <(ls -lhrt dirname)
必须符合您的需要。
tee
看看:
seq 1 12 | tee > >(tail -n4) >(head -n4)
1
2
3
4
9
10
11
12
但这可能会在终端上呈现奇怪的东西,为了防止这种情况,您可以将整个管道传输到cat
:
seq 1 12 | tee > >(tail -n4) >(head -n4) | cat
1
2
3
4
9
10
11
12
ls -lhrt dirname | tee > >(tail -n5) >(head -n5) | cat
必须做好这份工作。
files=$(seq 1 12) out='' in=''
for i in {1..4};do
in+=${files%%$'\n'*}$'\n'
files=${files#*$'\n'}
out=${files##*$'\n'}$'\n'${out}
files=${files%$'\n'*}
done
echo "$in${out%$'\n'}"
1
2
3
4
9
10
11
12
files=$(ls -lhrt dirname) out='' in=''
for i in {1..5};do
in+=${files%%$'\n'*}$'\n'
files=${files#*$'\n'}
out=${files##*$'\n'}$'\n'${out}
files=${files%$'\n'*}
done
echo "$in${out%$'\n'}"
seq 1 100000 | sed -e ':a;N;4p;5,${s/^[^\n]*\n//;};$!ba;'
1
2
3
4
99997
99998
99999
100000
然后
ls -lhrt dirname | sed -e ':a;N;5p;6,${s/^[^\n]*\n//;};$!ba;'
答案 2 :(得分:1)
如何添加这样的换行符:
files=$(ls -lhrt dirname) && echo -e "${files}\n" | head -5 && echo -e "${files}\n" | tail -5
说明:
-e
标志允许echo在此示例中解释转义符,例如\n
。
\n
本身是“新行”的转义序列。所以它只是在echoed变量之后添加一个新行。
${ }
被称为Brace Expansion。由于我将字符串放在引号中,${}
会将变量扩展为字符串。
答案 3 :(得分:0)
即使它是BASH的要求,我也只是把ZSH线放在这里
echo dirname/*(.om[1,5]) dirname/*(.om[-5,-1])
这将返回files
的列表,其中包含5个最旧和5个最新文件(基于修改时间)。基于ls -lrth
的其他解决方案可能会返回目录或链接或管道或其他任何内容。
您可以用任何内容替换echo
,但是您要求找到文件的方法,因此ZSH中的正确答案是上面的glob(没有echo
)
它的工作原理如下:
dirname/*
:取所有数学字符串(
:open glob specifier .
:仅返回普通文件om
:根据修改时间对其进行排序[1,5]
返回前五位或[-5,-1]
返回前五位)
:关闭glob说明符有关zsh globbing的更多信息,请访问: http://www.bash2zsh.com/zsh_refcard/refcard.pdf