在Bash中,我想创建一个函数,该函数返回与特定模式匹配的最新文件的文件名.例如,我有一个文件目录,如:
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
Run Code Online (Sandbox Code Playgroud)
我想要以'b2'开头的最新文件.我怎么在bash中这样做?我需要在我的~/.bash_profile脚本中有这个.
les*_*ana 199
该ls命令有一个-t按时间排序的参数.然后你可以抓住第一个(最新的)head -1.
ls -t b2* | head -1
Run Code Online (Sandbox Code Playgroud)
但要注意:为什么你不应该解析ls的输出
我的个人观点:ls当文件名可以包含空格或换行等有趣字符时,解析是危险的.如果你可以保证文件名不包含有趣的字符,那么解析ls是非常安全的.
如果您正在开发一个脚本,该脚本在很多不同情况下由许多系统上的许多人运行,那么我非常建议不要解析ls.
以下是如何"正确":如何在目录中找到最新(最新,最早,最旧)的文件?
unset -v latest
for file in "$dir"/*; do
[[ $file -nt $latest ]] && latest=$file
done
Run Code Online (Sandbox Code Playgroud)
Bor*_*ski 12
结合find并且ls效果很好
解决方案:
find . -name "my-pattern" ... -print0 |
xargs -r -0 ls -1 -t |
head -1
Run Code Online (Sandbox Code Playgroud)
让我们分解一下:
随着find我们可以匹配所有有趣的文件是这样的:
find . -name "my-pattern" ...
Run Code Online (Sandbox Code Playgroud)
然后使用-print0我们可以安全地将所有文件名传递到ls这样:
find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t
Run Code Online (Sandbox Code Playgroud)
ls -t将按修改时间(最新的第一个)对文件进行排序,并在一行中打印一个.您可以使用-c按创建时间排序.注意:这将破坏包含换行符的文件名.
最后head -1得到排序列表中的第一个文件.
注意: xargs对参数列表的大小使用系统限制.如果此尺寸超过,xargs将ls多次调用.这将打破排序,也可能打破最终输出.跑
xargs --show-limits
Run Code Online (Sandbox Code Playgroud)
检查你的系统限制.
注2:使用find . -maxdepth 1 -name "my-pattern" -print0如果你不想通过子文件夹进行搜索文件.
这是必需的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
}
Run Code Online (Sandbox Code Playgroud)
它仅使用Bash内置函数,并且应处理名称包含换行符或其他不寻常字符的文件。
您可以stat与文件 glob 和装饰排序取消装饰一起使用,并在前面添加文件时间:
$ stat -f "%m%t%N" b2* | sort -rn | head -1 | cut -f2-
Run Code Online (Sandbox Code Playgroud)
正如评论中所述,最好的跨平台解决方案可能是使用 Python、Perl、Ruby 脚本。
对于此类事情,我倾向于使用 Ruby,因为它非常像 awk,可以轻松地编写小型、可丢弃的脚本,但可以直接从命令行获得 Python 或 Perl 的强大功能。
这是红宝石:
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'
Run Code Online (Sandbox Code Playgroud)
这会获取当前工作目录中的最新文件。
**/*您还可以通过使用inglob或 limit 到匹配的文件b2*等来使 glob 递归
一个 Bash 函数,用于在与模式匹配的目录下查找最新文件
#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"
Run Code Online (Sandbox Code Playgroud)
印刷:
result: /tmp/files_to_move/file2.txt
Run Code Online (Sandbox Code Playgroud)
或者,如果脆弱的 bash parlor 技巧分包给 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"
Run Code Online (Sandbox Code Playgroud)
印刷:
result: /tmp/files_to_move/file2.txt
Run Code Online (Sandbox Code Playgroud)
使用查找命令。
假设您使用的是 Bash 4.2+,请使用-printf '%T+ %p\n'文件时间戳值。
find $DIR -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2
Run Code Online (Sandbox Code Playgroud)
例子:
find ~/Downloads -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2
Run Code Online (Sandbox Code Playgroud)
有关更有用的脚本,请参阅此处的find-latest脚本:https : //github.com/l3x/helpers