Linux bash script to find and delete oldest file with special characters and whitespaces in a directory tree if condtion is met
If you really want to process files with spaces, new lines and any special characters, you must consider using a null \0
as the limit for file names, like this:
dir=/mnt/volume0/recordings
find "$dir"/ -type f -printf '%T+ %p\0' |
sort -zk1,1 |
head -n1 -z |
cut -zd ' ' -f2- |
xargs -0 echo rm -f --
This will find files in a dir and forcefully will remove the oldest file (only one) (if the echo is removed, test it before actually using it).
Set modified date of a file to the oldest in a directory
You can loop over all files, and whenever you find one that's older than file_example
, you can update file_example
:
for f in ./*; do
# Skip directories
[[ -d $f ]] && continue
# Compare and update
[[ $f -ot file_example ]] && touch file_example -r "$f"
done
If you want to include hidden files, you can either loop with for f in ./* ./.*
, or use shopt -s dotglob
first.
This can be packaged in a shell function:
settooldest() {
local file=$1
local dir=$2
local f
for f in "$dir"/*; do
[[ -d $f ]] && continue
[[ $f -ot $file ]] && touch "$file" -r "$f"
done
}
Which is called like
settooldest file_example path/to/dir
removing all but X oldest directories on FreeBSD via Bash (no -printf, with spaces, no zsh)
... | awk 'NR>5' | while read -r timestamp filename; do rm -rf "${filename}"; done
When there are more fields than variables specified in read
, the remainder is simply lumped together in the last specified variable. In our case, we extract the timestamp and use everything else as-is for the file name. We iterate the output and run an rm
for each entry.
I would recommend doing a test run with echo
instead of rm
so you can verify the results first.
Alternately, if you'd prefer an xargs -0
version:
... | awk 'NR>5' | while read -r timestamp filename; do printf "%s\0" "${filename}"; done | xargs -0 rm -rf
This also uses the while read
but prints each filename with a null byte delimiter which can be ingested by xargs -0
.
Make tree command print & instead of & (And other special characters) on JSON file
Until this can be fixed and deployed everywhere:
tree . -J | recode html..utf8
But this fail with "piña colada" or "你好"
The perl alternative works with all:
tree . -J | perl -n -mHTML::Entities -e 'print HTML::Entities::decode_entities($_)'
Sample output:
[
{"type":"directory","name":".","contents":[
{"type":"file","name":"a"},
{"type":"file","name":"a&"},
{"type":"file","name":"<a>&c"},
{"type":"file","name":"b"},
{"type":"file","name":"c"},
{"type":"file","name":"d"},
{"type":"file","name":"e"},
{"type":"file","name":"f"},
{"type":"file","name":"filename.R10011.out"},
{"type":"file","name":"g"},
{"type":"file","name":"h"},
{"type":"file","name":"i"},
{"type":"file","name":"j"},
{"type":"file","name":"k"},
{"type":"file","name":"l"},
{"type":"file","name":"piña colada"},
{"type":"directory","name":"r","contents":[
]},
{"type":"file","name":"你好"}
]},
{"type":"report","directories":1,"files":17}
]
xargs and find, rm complaining about \n (newline) in filename
The ls
appends a newline and the last xargs -0 says the newline is part of the file name.
Run the last xargs with -d '\n'
instead of -0
.
BTW, due to the way xargs works, your whole pipe is a bug waiting to happen. Consider a really long file name list produced by the find
, so that the xargs -0 ls
runs ls
multiple times with subsets of the filenames. Only the oldest of the last ls
invocation will make it past the tail -1
. If the oldest file is actually, say, the very first filename output by find
, you are deleting a younger file.
How to find the last field using 'cut'
You could try something like this:
echo 'maps.google.com' | rev | cut -d'.' -f 1 | rev
Explanation
rev
reverses "maps.google.com" to bemoc.elgoog.spam
cut
uses dot (ie '.') as the delimiter, and chooses the first field, which ismoc
- lastly, we reverse it again to get
com
Check if a file exists with a wildcard in a shell script
For Bash scripts, the most direct and performant approach is:
if compgen -G "${PROJECT_DIR}/*.png" > /dev/null; then
echo "pattern exists!"
fi
This will work very speedily even in directories with millions of files and does not involve a new subshell.
Source
The simplest should be to rely on ls
return value (it returns non-zero when the files do not exist):
if ls /path/to/your/files* 1> /dev/null 2>&1; then
echo "files do exist"
else
echo "files do not exist"
fi
I redirected the ls
output to make it completely silent.
Here is an optimization that also relies on glob expansion, but avoids the use of ls
:
for f in /path/to/your/files*; do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
[ -e "$f" ] && echo "files do exist" || echo "files do not exist"
## This is all we needed to know, so we can break after the first iteration
break
done
This is very similar to grok12's answer, but it avoids the unnecessary iteration through the whole list.
Split linux files based on condition
You need to trim the underscore and trailing text from each line. %%_*
does that:
while read -r line ; do
echo "$line" >> "${line%%_*}.txt"
done < split.txt
Explanation:
%
: trim trailing text%%
: find the longest possible match_*
: an underscore and everything after
Related Topics
Perf: Strange Relation Between Software Events
Ssl/Qsslsocket_Openssl.Cpp:1414: Error: Q_Ssl_Ctrl Was Not Declared in This Scope Error
Change The Rlimit_Nproc in Linux
Cygwin Xwin Server Randomly Loses Connection
Fortran: How to Get The Node Name of a Cluster
How Does Apparmor Handle Linux-Kernel Mount Namespaces
Google Suggest Query Using Curl
How to Run a Linux Executable from Any Directory in Terminal
How to Join Columns of Two Files in Unix System
Why Does Automating Sftp with Expect Hang After Sending The Password
How to Source a Simple Bash Script
Kernel Preemption While Holding Spinlock
The Button.Connect Syntax in Genie
How to Ensure Data Reaches Storage, Bypassing Memory/Cache/Buffered-Io
Bash - While Read Line from File Print First and Second Column
Aosp Build Error: Unrecognized Module Type "Hidl_Package_Root"
Save The Result of Ls Command in The Remote Sftp Server on Local Machine