Bash: find files within file size range and report their names to a file - bash

I would like to write a Bash script that selects files within a given folder with file size between 10kB and 100kB. This list of files should be written to a new file. Something like:
fileSelector ~/my-folder-containing-files ~/my-report-file
Can you help me develop such a script using bash?

If you just want to get a list of files within a specific size range, you can try:
$ find . -type f -size +10k -size -101k -exec ls {} \;
notice that since the size is calculated to be rounded up to the next unit, you would actually get a size range between 10241 to 102400 bytes from the above expression
if you want to make the limits to be byte-precise, you can use:
$ find . -type f -size +10239c -size -102401c -exec ls {} \;

Related

How to check the size of all files inside a directory and empty it if it is exceeding certain size

I am a bit new to the bash scripting and have a scenario on which i need to know the efficient way to complete.
I need to check the size of all the files inside a directory and if the size of any files exceeds certain limit i need to empty those files and then send email to a mail ID with details like name of the files which are emptied, the original size, the current size after emptying.
Found lots of blog on the same topic but just wanted to check the most efficient way i can complete the above scenario.
Thanks
Was able complete the above scenario with the help of find command.
rm -f logFile*
find . -type f -size +20k -exec du -sh {} \; >> logFile.txt
cat logFile*
find . -type f -size +20k -exec truncate -s 0 {} \;

How to move all files with fewer than 5 bytes in BASH?

I have a folder containing many audio files, but some are ~4 bytes and seem to contain nothing, they are 0 seconds long and have no sound. I want to move them to a folder called "temp/".
How can I move all of the files in the folder that have fewer than 5 bytes to this folder?
Find!
You can use find to do this for you:
find . -type f -maxdepth 1 -size -5c -exec mv {} temp/ \;
Explanation
-size -5c grabs all the files less than 5 bytes. The - indicates less than and the c indicates bytes.
-maxdepth 1 prevents you from trying to move the files on top of themselves when it tries to recurse into temp/ (after moving your initial files).
-exec mv {} temp/ \; simply runs mv on each file to put them in temp (the {} is substituted for the name of the file). The escaped semicolon marks the end of the mv command for exec.
There are other sizes available as well:
`b' for 512-byte blocks (this is the default if no suffix is
used)
`c' for bytes
`w' for two-byte words
`k' for Kilobytes (units of 1024 bytes)
`M' for Megabytes (units of 1048576 bytes)
`G' for Gigabytes (units of 1073741824 bytes)
find -size 1c will give you all files that are exactly one byte.
As #user1666959 mentions, you can also use find . -type f -size -4c, which will find all files in the current directory (and subdirectories), that are 4 bytes and smaller.
$ find . -maxdepth 1 -type f -size -4c -exec mv {} temp/ \;
(Yes, you will need the trailing \;.
Note that find -size allows for other exact file size matches (such as 1k), but also allows you to search for files that take up the designated number of blocks on the disk (leaving off the unit).
$ man find
Provides a heap more info about how to use it to search.
find . -maxdepth 1 -type f -size -5c -exec mv '{}' temp/ \;
One solution would be:
find . -type f -maxdepth 1 | xargs du | sort -n |grep "^[0-5]\t"|sed "s/[0-5]//"|sed "s/^.//"|xargs -I ARG mv ARG temp/
It finds all files, lists their sizes, sorts by that, takes all that are size 0,1,2,3,4,5, gets just the filenames, and then runs the mv command on them!

Imagemagick with find in bash script : output in current folder

I have subfolders with png images inside. I want to convert them to jpeg with a static name (there is only one image per folder). The images need to be outputted in the same folder as the original image.
This bash script
#! /bin/sh
find . -type f -name '*.png' -exec convert "{}" *OPTIONS* mydefinedname.jpg \;
doesn't work because the output is always the root folder, so it erases each previous jpeg with the current one.
Ho to tell convert ? The help file isn't clear on this point.
Instead of -exec, use -execdir, which runs the command in the directory the file is in, rather than the current working directory:
find . -type f -name '*.png' -execdir convert "{}" *OPTIONS* mydefinedname.jpg \;

Shell Script for Flip Canvas Vertical

I have M1.jpg M2.jpg ....... M100.jpg in /Users/KanZ/Desktop/Project/Test/
I would like Flip Canvas Vertical them, save and replace them instead of old files. How can I write the script for this problem?
You can do that with convert, with a little help from find so you don't have to write a loop:
find /Users/KanZ/Desktop/Project/Test/ -type f -name "M*.jpg" -exec convert {} -flip {} \;
Explanation:
find /Users/KanZ/Desktop/Project/Test/ - Invoke find tool and specify the base directory to perform the search for files recursively.
-type f - Find only files
-name "M*.jpg" - Find only files with names that start with M and end with .jpg
-exec ... \; - For each such file found, perform the command in ...
convert {} -flip {} - This is the actual command that flips your images. The {}'s are syntax as part of the find command, they represent where the found files from find would be substituted into. So here we are saying to use convert to flip the images vertically with the -flip option, but keep the file names unchanged.
Alternatively:
You can also do it with a loop and globbing:
for file in /Users/KanZ/Desktop/Project/Test/M*.jpg; do convert "$file" -flip "$file"; done

Find all files with a filename beginning with a specified string?

I have a directory with roughly 100000 files in it, and I want to perform some function on all files beginning with a specified string, which may match tens of thousands of files.
I have tried
ls mystring*
but this returns with the bash error 'Too many arguments'. My next plan was to use
find ./mystring* -type f
but this has the same issue.
The code needs to look something like
for FILE in `find ./mystring* -type f`
do
#Some function on the file
done
Use find with a wildcard:
find . -name 'mystring*'
ls | grep "^abc"
will give you all files beginning (which is what the OP specifically required) with the substringabc.
It operates only on the current directory whereas find operates recursively into sub folders.
To use find for only files starting with your string try
find . -name 'abc'*
If you want to restrict your search only to files you should consider to use -type f in your search
try to use also -iname for case-insensitive search
Example:
find /path -iname 'yourstring*' -type f
You could also perform some operations on results without pipe sign or xargs
Example:
Search for files and show their size in MB
find /path -iname 'yourstring*' -type f -exec du -sm {} \;

Resources