简体   繁体   中英

Bash script to cd into newest directory within a directory

I am trying to add a function to a data collection bash script I am writing. The intention would be to point to a specific directory, and then cd into the NEWEST directory within the parents.

Pseudocode:

cd top_dir
    for each dir in top_dir:
      age = dir.age
      if age < least_age:
        least_age = age
        newest_dir = dir

    cd newest_dir

I have tried using cd "$( find "$1"/* -prune -type d 2>/dev/null | xargs stat -c "%Y %n" 2>/dev/null | sort -nr | head -n 1 | cut -d " " -f 2-)" from this post , but that instead cd's me into the newest directory on my computer.

The intention would be for a directory structure like below:

parent_dir:
  child_1 | Last Edited 1 Hr Ago
  child_2 | Last Edited 1 Yr Ago
  child_3 | Last Edited 2 Yr Ago
  child_4 | Last Edited 1 Min Ago
  child_5 | Last Edited 1 Week Ago

The command would cd me into child_4

The code you are trying to use is intended to be the body of a function; calling the function sets $1 properly. By itself, $1 probably isn't set, and so find operators on ""/ (same as / ), not top_dir .

new_cd () {
  cd "$( find "$1"/* -prune -type d 2>/dev/null | xargs stat -c "%Y %n" 2>/dev/null | sort -nr | head -n 1 | cut -d " " -f 2-)"
}

new_cd top_dir

This can be simplified a little. There's no need to use find or xargs ; a simple loop will do. And since you have a function now, there's no need to cram everything in one line.

new_cd () {
  new_d=$(for d in "$1"/*/; do
      stat -c "%Y %n" "$d" 2> /dev/null
  done | sort -nr |
         head -n |
         cut -d " " -f 2-)
  cd "$new_d"
}

This has one minor drawback: the command substitution will eat any trailing newlines in the output of cut , so make sure none of your directory names ends with a newline character. (This extremely minor bug can be fixed, but it probably isn't worth doing so; just be aware of it.)

It also has a bigger drawback: since non -trailing newlines aren't eaten, you cannot assume the output of the loop consists of exactly one file per line; a single file could occupy multiple lines. The easiest fix is to avoid directory names with newlines. A more robust fix abandons the pipeline.

new_cd () {
  local newest_time newest_d
  for d in "$1"/*/; do
    t=$(stat -c "%Y" "$d")
    if (( t > newest_time )); then
      newest_time=$t
      newest_d=$d
    fi
  done
  cd "$newest_d"
}

You can find the most recent subdirectory using ls -ldt */ | head -1 ls -ldt */ | head -1 : the t option sorts files by date and */ matches only subdirectories, not files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM