Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
我想要获取以'b2'开头的最新文件。在bash中应该怎么做?我需要将这个命令写进我的~/.bash_profile
脚本中。
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
我想要获取以'b2'开头的最新文件。在bash中应该怎么做?我需要将这个命令写进我的~/.bash_profile
脚本中。
ls
命令有一个参数 -t
可以按时间排序。然后你可以用 head -1
来获取第一个(最新的)。ls -t b2* | head -1
unset -v latest
for file in "$dir"/*; do
[[ $file -nt $latest ]] && latest=$file
done
要了解更多,请阅读如何在目录中找到最新(最新,最早,最旧)的文件?
ls
的一行代码,那么 printf "%s\n" b2* | head -1
就可以满足你的需求。 - David Ongarob2.10_5_2
也会破坏这个解决方案。 - Eponymousfind
和ls
的组合适用于以下情况:
find . -name "my-pattern" -print0 |
xargs -r -0 ls -1 -t |
head -1
让我们来分解一下:
使用find
命令,我们可以像这样匹配所有感兴趣的文件:
find . -name "my-pattern" ...
然后使用-print0
,我们可以安全地将所有文件名传递给ls
,像这样:
find . -name "my-pattern" -print0 | xargs -r -0 ls -1 -t
可以在此处添加其他find
搜索参数和模式
find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t
ls -t
命令会按修改时间排序文件(最新的在前面),每行打印一个文件名。你可以使用 -c
选项按创建时间排序。注意:如果文件名中包含换行符,该命令会出错。
最后,head -1
命令获取排序后列表中的第一个文件。
注意:xargs
命令使用系统限制来控制参数列表的大小。如果列表大小超过限制,xargs
将多次调用 ls
命令。这将破坏排序,可能也会破坏最终输出结果。请运行
xargs --show-limits
检查您系统的限制。
注2:如果您不想通过子文件夹搜索文件,请使用find . -maxdepth 1 -name "my-pattern" -print0
。
注3:正如@starfry所指出的那样,xargs
的-r
参数将防止调用ls -1 -t
,如果find
没有匹配到任何文件。感谢您的建议。
find . -name "my-pattern" ... -print0
gives me find: paths must precede expression: \
...'` - Jaakko...
代表“更多参数”。如果你不需要它,就省略掉。 - Boris Brodski这是所需 Bash 函数的可能实现:
# Print the newest file, if any, matching the given pattern
# Example usage:
# newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
# Use ${1-} instead of $1 in case 'nounset' is set
local -r glob_pattern=${1-}
if (( $# != 1 )) ; then
echo 'usage: newest_matching_file GLOB_PATTERN' >&2
return 1
fi
# To avoid printing garbage if no files match the pattern, set
# 'nullglob' if necessary
local -i need_to_unset_nullglob=0
if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
shopt -s nullglob
need_to_unset_nullglob=1
fi
newest_file=
for file in $glob_pattern ; do
[[ -z $newest_file || $file -nt $newest_file ]] \
&& newest_file=$file
done
# To avoid unexpected behaviour elsewhere, unset nullglob if it was
# set by this function
(( need_to_unset_nullglob )) && shopt -u nullglob
# Use printf instead of echo in case the file name begins with '-'
[[ -n $newest_file ]] && printf '%s\n' "$newest_file"
return 0
}
它仅使用Bash内置命令,并且应该能够处理文件名包含换行符或其他不寻常字符的文件。
nullglob_shopt=$(shopt -p nullglob)
,然后稍后使用 $nullglob
将 nullglob
恢复到先前的状态。 - gniourf_gniourfnullglob_shopt
),因为如果变量值错误,可能会发生非常糟糕的事情。 - pjh猫
*”!即使这需要更多的工作,它也有展示概念的好处。加一分! - Pryftan使用find命令。
假设您正在使用Bash 4.2+,可以使用-printf '%T+ %p\n'
来获取文件的时间戳值。
find $DIR -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2
例子:
find ~/Downloads -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2
如需更实用的脚本,请查看此处的find-latest脚本:https://github.com/l3x/helpers
find
,因为-printf
选项是非标准的(通常情况下,这仅适用于Linux操作系统)。 - tripleeestat
和文件通配符一起使用,通过装饰-排序-去装饰的方式,在文件时间前面添加它:$ stat -f "%m%t%N" b2* | sort -rn | head -1 | cut -f2-
正如评论中所述,最好的跨平台解决方案可能是使用Python、Perl或Ruby脚本。
在这种情况下,我倾向于使用Ruby,因为它非常类似于awk,可以轻松编写小型且可随意删除的脚本,同时具有从命令行中读取Python或Perl的强大功能。
以下是一个Ruby脚本的示例:
ruby -e '
# index [0] for oldest and [-1] for newest
newest=Dir.glob("*").
reject { |f| File.directory?(f)}.
sort_by { |f| File.birthtime(f) rescue File.mtime(f)
}[-1]
p newest'
获取当前工作目录中最新的文件。
您还可以通过在glob
中使用** / *
进行递归,或使用b2*
等限制匹配文件。
stat
的Mac/FreeBSD版本,如果我正确记得它的选项。要在其他平台上获得类似的输出,您可以使用stat -c $'%Y\t%n' b2* | sort -rn | head -n1 | cut -f2-
。 - Jeffrey Cashstat
行为的这种粒度级别的控制。如果您需要一种便携式解决方案,具有讽刺意味的是,也许编写一个Perl或Python脚本会更好。 - tripleee#1. Make a bash function:
newest_file_matching_pattern(){
find $1 -name "$2" -print0 | xargs -0 ls -1 -t | head -1
}
#2. Setup a scratch testing directory:
mkdir /tmp/files_to_move;
cd /tmp/files_to_move;
touch file1.txt;
touch file2.txt;
touch foobar.txt;
#3. invoke the function:
result=$(newest_file_matching_pattern /tmp/files_to_move "file*")
printf "result: $result\n"
输出:
result: /tmp/files_to_move/file2.txt
如果您更喜欢使用 Python 解释器,那么以下命令也能实现同样的功能:
#!/bin/bash
function newest_file_matching_pattern {
python - <<END
import glob, os, re
print(sorted(glob.glob("/tmp/files_to_move/file*"), key=os.path.getmtime)[0]);
END
}
result=$(newest_file_matching_pattern)
printf "result: $result\n"
输出:
result: /tmp/files_to_move/file2.txt
不寻常的文件名(例如包含有效的\n
字符的文件)可能会对此类解析造成严重影响。以下是使用Perl的一种方法:
perl -le '@sorted = map {$_->[0]}
sort {$a->[1] <=> $b->[1]}
map {[$_, -M $_]}
@ARGV;
print $sorted[0]
' b2*
这里使用了Schwartzian变换。
结合find
、stat
、sort
、cut
和tail
。
find
命令查找文件-type f
(匹配名称-name 'b2*'
)xargs stat
命令对这些文件进行统计,打印出自纪元以来的%Y
秒和文件名%n
sort
命令对其进行排序cut
命令从第2个字段开始截取-f
2 onwards 2-
(以制表符分隔)tail
命令获取排序后的最新文件的最后一个-n 1
适用于所有的shell和POSIX兼容系统(据我所知)
tab=$(printf '\t');
find . -type f -print0 |
xargs -0 stat --format "%Y$tab%n" |
sort |
cut -f 2- |
tail -n 1
请随意使用"$tab"来代替一个实际的制表符,这在SO上不起作用。
OP要求过滤以b2开头的文件名,所以应该是
tab=$(printf '\t');
find . -type f -name 'b2*' -print0 |
xargs -0 stat --format "%Y$tab%n" |
sort |
cut -f 2- |
tail -n 1
有一种更高效的方法可以实现这个目标。请考虑以下命令:
find . -cmin 1 -name "b2*"
这个命令使用通配符搜索"b2*",找到刚好一分钟前生成的最新文件。如果你想要过去两天内的文件,最好使用以下命令:
find . -mtime 2 -name "b2*"
“.”代表当前目录。 希望这可以帮到你。
"