Get the newest directory in bash to a variables

后端 未结 8 2071
北恋
北恋 2020-12-13 13:17

I would like to find the newest sub directory in a directory and save the result to variable in bash.

Something like this:

ls -t /backups | head -1 &         


        
相关标签:
8条回答
  • 2020-12-13 13:32

    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:

    echo "test" > test.txt
    ls -t /backups | head -1
    test.txt
    

    The result is test.txt showing up instead of the last modified directory.

    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:

    find /backups/* -type d -prune -exec ls -d {} \; |tail -1
    

    Just swap the "/backups/" portion for your actual path.

    If you want to avoid showing an absolute path in a bash script, you could always use something like this:

    LOCALPATH=/backups
    DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1)
    
    0 讨论(0)
  • 2020-12-13 13:34

    This ia a pure Bash solution:

    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.

    0 讨论(0)
  • 2020-12-13 13:43

    Your "something like this" was almost a hit:

    BACKUPDIR=$(ls -t ./backups | head -1)
    

    Combining what you wrote with what I have learned solved my problem too. Thank you for rising this question.

    Note: I run the line above from GitBash within Windows environment in file called ./something.bash.

    0 讨论(0)
  • 2020-12-13 13:45
    BACKUPDIR=$(ls -td /backups/*/ | head -1)
    

    $(...) evaluates the statement in a subshell and returns the output.

    0 讨论(0)
  • 2020-12-13 13:52

    There is a simple solution to this using only ls:

    BACKUPDIR=$(ls -td /backups/*/ | head -1)
    
    • -t orders by time (latest first)
    • -d only lists items from this folder
    • */ only lists directories
    • head -1 returns the first item

    I didn't know about */ until I found Listing only directories using ls in bash: An examination.

    0 讨论(0)
  • 2020-12-13 13:55

    With GNU find you can get list of directories with modification timestamps, sort that list and output the newest:

    find . -mindepth 1 -maxdepth 1 -type d -printf "%T@\t%p\0" | sort -z -n | cut -z -f2- | tail -z -n1
    

    or newline separated

    find . -mindepth 1 -maxdepth 1 -type d -printf "%T@\t%p\n" | sort -n | cut -f2- | tail -n1
    

    With POSIX find (that does not have -printf) you may, if you have it, run stat to get file modification timestamp:

    find . -mindepth 1 -maxdepth 1 -type d -exec stat -c '%Y %n' {} \; | sort -n | cut -d' ' -f2- | tail -n1
    

    Without stat a pure shell solution may be used by replacing [[ bash extension with [ as in this answer.

    0 讨论(0)
提交回复
热议问题