获取 bash 中的最新目录到变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9275964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get the newest directory in bash to a variables
提问by Jonathan
I would like to find the newest sub directory in a directory and save the result to variable in bash.
我想在目录中找到最新的子目录并将结果保存到bash中的变量中。
Something like this:
像这样的东西:
ls -t /backups | head -1 > $BACKUPDIR
Can anyone help?
任何人都可以帮忙吗?
回答by Femaref
BACKUPDIR=$(ls -td /backups/*/ | head -1)
$(...)
evaluates the statement in a subshell and returns the output.
$(...)
在子shell中评估语句并返回输出。
回答by Martin
There is a simple solution to this using only ls
:
有一个简单的解决方案,只使用ls
:
BACKUPDIR=$(ls -td /backups/*/ | head -1)
-t
orders by time (latest first)-d
only lists items from this folder*/
only lists directorieshead -1
returns the first item
-t
按时间排序(最新在先)-d
仅列出此文件夹中的项目*/
只列出目录head -1
返回第一项
I didn't know about */
until I found Listing only directories using ls in bash: An examination.
*/
直到我发现 在 bash 中使用 ls 只列出目录:一个检查,我才知道。
回答by pjh
This ia a pure Bash solution:
这是一个纯 Bash 解决方案:
topdir=/backups
BACKUPDIR=
# Handle subdirectories beginning with '.', and empty $topdir
shopt -s dotglob nullglob
for file in "$topdir"/* ; do
[[ -L $file || ! -d $file ]] && continue
[[ -z $BACKUPDIR || $file -nt $BACKUPDIR ]] && BACKUPDIR=$file
done
printf 'BACKUPDIR=%q\n' "$BACKUPDIR"
It skips symlinks, including symlinks to directories, which may or may not be the right thing to do. It skips other non-directories. It handles directories whose names contain any characters, including newlines and leading dots.
它跳过符号链接,包括指向目录的符号链接,这可能是也可能不是正确的做法。它跳过其他非目录。它处理名称包含任何字符的目录,包括换行符和前导点。
回答by wholehogsoftware
The above solution doesn't take into account things like files being written and removed from the directory resulting in the upper directory being returned instead of the newest subdirectory.
上面的解决方案没有考虑到文件被写入和从目录中删除导致返回上层目录而不是最新的子目录之类的事情。
The other issue is that this solution assumes that the directory only contains other directories and not files being written.
另一个问题是此解决方案假定目录仅包含其他目录而不包含正在写入的文件。
Let's say I create a file called "test.txt" and then run this command again:
假设我创建了一个名为“test.txt”的文件,然后再次运行此命令:
echo "test" > test.txt
ls -t /backups | head -1
test.txt
The result is test.txt showing up instead of the last modified directory.
结果是显示 test.txt 而不是最后修改的目录。
The proposed solution "works" but only in the best case scenario.
建议的解决方案“有效”,但仅适用于最佳情况。
Assuming you have a maximum of 1 directory depth, a better solution is to use:
假设您最多有 1 个目录深度,更好的解决方案是使用:
find /backups/* -type d -prune -exec ls -d {} \; |tail -1
Just swap the "/backups/" portion for your actual path.
只需将“/backups/”部分交换为您的实际路径。
If you want to avoid showing an absolute path in a bash script, you could always use something like this:
如果你想避免在 bash 脚本中显示绝对路径,你总是可以使用这样的东西:
LOCALPATH=/backups
DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1)
回答by Sven
Well, I think this solution is the most efficient:
嗯,我认为这个解决方案是最有效的:
path="/my/dir/structure/*"
backupdir=$(find $path -type d -prune | tail -n 1)
Explanation why this is a little better:
解释为什么这更好一点:
We do not need sub-shells (aside from the one for getting the result into the bash variable).
We do not need a useless -exec ls -d
at the end of the find
command, it already prints the directory listing.
We can easily alter this, e.g. to exclude certain patterns. For example, if you want the second newest directory, because backup files are first written to a tmp dir in the same path:
我们不需要子外壳(除了用于将结果放入 bash 变量的外壳)。我们不需要命令-exec ls -d
末尾的无用find
,它已经打印了目录列表。我们可以很容易地改变这一点,例如排除某些模式。例如,如果您想要第二个最新的目录,因为备份文件首先写入同一路径中的 tmp 目录:
backupdir=$(find $path -type -d -prune -not -name "*temp_dir" | tail -n 1)
回答by Kind Jason
To get the newest folder using ls -t
you may have to differentiate files from folders if your directory doesn't have only directories. Using a simple loop you will have a safe and fast result and also allowing to easily implement different filters in the future:
ls -t
如果您的目录不只有目录,则要使用最新的文件夹,您可能必须将文件与文件夹区分开来。使用一个简单的循环,您将获得安全快速的结果,并且将来还可以轻松实现不同的过滤器:
while read i ; do if [ -d "${i}" ] ; then newestFolder="${i}" ; break ; fi ; done < <(ls -t)
Elaborated block:
精心制作的方块:
while read currentItemOnLoop # While reading each line of the file
do
if [ -d "${currentItemOnLoop}" ] # If the item is a folder
then
newestFolder="${currentItemOnLoop}" # Then save it into the "newestFolder" variable
break # and stop the loop
else
continue # Look for the next newest item
fi
done < <(ls -t) # Sending the result of "ls -t" as a "file" to the "while read" loop
Beware of the continue
logic on my elaborated block:
当心continue
我精心设计的块上的逻辑:
else
continue # Look for the next newest item
You won't use it. I've put it there just for the sake of your visibility as in this case it wouldn't affect the results.
你不会使用它。我把它放在那里只是为了你的可见性,因为在这种情况下它不会影响结果。