As the title says, I just started with linux mint and am falling in love with bash scripts 😍 Actually I’m not sure if it’s considered a script, but I want to delete the last 2 files in all subfolders in a folder. So far I’ve (after great effort) got the terminal to list the files, but I want to delete them. Here is how I get them listed:
for f in *; do ls $f | tail -n 2; done
All their names come satisfyingly up in the terminal. Now what? I tried adding | xargs rm but that didn’t delete them. I also tried something with find command but that didn’t work either. Some folders have 3 items, so I want to delete #2 and 3. Some folders have 15 items so I want to delete #14 and 15. Folders are arranged by name, so it’s always the last 2 that I want to delete.
It’s frustrating to be sooooo clooooose, but also very fun. Any help is appreciated!
EDIT: Thanks for the awesome help guys! The next part of this is to move all the .html files into one folder (named “done”), prepending their name with an integer. So far I got:
n=1; for f in *; do find ./"$f" -type f | sort | xargs mv done/"$n$f"; n=$((n+1)); done
but that is… not really doing anything. The closest I have gotten so far is some error like
mv: Missing destination file operand
Any help is again appreciated!
The breakdown:
#! /bin/bash
- This heads every bash script and is necessary to tell your shell environment what interpreter to use for the script. In this case we’re using/bin/bash
to execute the script.fileList="$(find ~/path/to/dir/with/html/files -name '*.html' | sort)"
- What this command is doing is creating a variable calledfileList
using command substitution. Command substitution encloses a command in"$()"
to tellbash
to execute the command(s) contained within the substitution group and save the output of the command(s) to the variable. In this case the commands are afind
command piped into asort
command.find ~/path/to/dir/with/html/files -name '*.html' | sort
- So this is the command set that will execute and the output of this command will be saved to the variablefileList
.num=1
- Here we’re creating a variable callednum
with a value of1
. This is for adding sequential numbers to the files as they are moved from their source directory to the destination directory.while IFS= read -r line; do
- This script uses awhile
loop to process each item saved to thefileList
variable. Within thewhile
loop, the moving and renaming of the files will take place.pad="$(printf '%03d' $num)"
- This is another variable being created using command substitution. What the command in the substitution group does is take thenum
variable and pad it with zeroes to be a three digit number.printf '%03d' $num
- This is the command that runs inside the substitution set.mv $line /path/to/dest/"$pad${line##*/}"
- This command actually moves and renames the file.((num++))
- Is a nice easy way to increment a number variable inbash
done<<<"$fileList"
- Is three parts.done
indicates the end of the while loop.<<<
is forheredoc
, which is a bash utility that allows you to pass a multiline chunk of text into a command. To pass a variable into a command withheredoc
you need to use three less than symbols (<<<
). Finally, is the variable holding the chunk of text we want fed into thewhile
loop, which is thefileList
variable (double quoted to insure proper expansion ignoring spaces and other nonstandard characters).And that’s the script! Let me know how it works for you.