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"
}