Compare folder size & conditional - bash

What i'm trying to do basically is to get the folder size and check if it's greater than X size to do some actions (move files externally)...but the conditionnal doesn't work.
#!/bin/bash
FOLDER_SIZE="5709119"
CHECK=$(du -s /var/backups/ | cut -f1)
echo "Current folder size $CHECK"
echo "Current SIZE LIMIT $FOLDER_SIZE"
if [[ $CHECK -gt $FOLDER_SIZE ]]
then
echo "$CHECK BIGGER THAN $FOLDER_SIZE"
else
echo "$CHECK SMALLER THAN $FOLDER_SIZE"
fi
The problem here is: i'm always getting the size of $check is smaller than $folder_size which not true since the $CHECK folder is mucher bigger than 5GB.
I'm getting as well this error when i run the script:
bk_script.sh: 35:bk_script.sh: [[: not found
Any hints will be much appreciated.

bk_script.sh: 35:bk_script.sh: [[: not found
How are you running your script? The error suggests you're doing something like sh bk_script.sh rather than ./bk_script.sh. Always do the latter so it uses the declared shell /bin/bash rather than /bin/sh. Plain sh does not have a [[ operator.

Related

Bash: base64 decode a file x times

During a scripting challenge, it was asked to me to decode X times (saying 100) a base64 files (base64.txt).
So I wrote this small bash script to do so.
for item in `cat base64.txt`;do
for count in {1..100};do
if [ $count -eq 1 ]; then
current=$(echo "$item" |base64 --decode)
else
current=$(echo "$current" |base64 --decode)
fi
if [ $count -eq 100 ]; then
echo $current
fi
done
done
It is working as expected, and I got the attended result.
What I am looking for now, is a way to improve this script, because I am far to be a specialist, and want to see what could improve the way I approach this kind of challenge.
Could some of you please give me some advice ?
decode X times (saying 100) a base64 file (base64.txt)
there is only 1 file, that contains 1 line in it.
Just read the content of the file, decode it 100 times and output.
state=$(<base64.txt)
for i in {1..100}; do
state=$(<<<"$state" base64 --decode)
done
echo "$state"
Notes:
Backticks ` are discouraged. Use $(...) instead. bash deprecated and obsolete syntax
for i in cat is a common antipattern in bash. How to read a file line by line in bash
If the file contains one line only, there is no need to iterate over the words in the file.
In bash echo "$item" | is a useless usage of echo (and is also a small risk that it may not work, when ex. item=-e). You can use a here string instead when in bash.

Unexpected end of file in while loop in bash

I am trying to write a bash script that will do the following:
Take a directory or file as input (will always begin with /mnt/user/)
Search other mount points for same file or directory (will always begin with /mnt/diskx)
Return value
So, for example, the input will be "/mnt/user/my_files/file.txt". It will search if ""/mnt/disk1/my_files/file.txt" exists and will incrementally look for each disk (disk2, disk3, etc) until it finds it or disk20.
This is what I have so far:
#/user/bin/bash
var=$1
i=0
while [ -e $check_var = echo $var | sed 's:/mnt/user:/mnt/disk$i+1:']
do
final=$check_var
done
It's incomplete yes, but I am not that proficient in bash so I'm doing a little at a time. I'm sure my command won't work properly yet either but right now I am getting an "unexpected end of file" and I can't figure out why.
There are many issues here:
If this is the actual code you're getting "unexpected end of file" on, you should save the file in Unix format, not DOS format.
The shebang should be #!/usr/bin/bash or #!/bin/bash depending on your system
You have to assign check_var before running [ .. ] on it.
You have to use $(..) to expand a command
Variables like $i are not expanded in single quotes
sed can't add numbers
i is never incremented
the loop logic is inverted, it should loop until it matches and not while it matches.
You'd want to assign final after -- not in -- the loop.
Consider doing it in even smaller pieces, it's easier to debug e.g. the single statement sed 's:/mnt/user:/mnt/disk$i+1:' than your entire while loop.
Here's a more canonical way of doing it:
#!/bin/bash
var="${1#/mnt/user/}"
for file in /mnt/disk{1..20}/"$var"
do
[[ -e "$file" ]] && final="$file" && break
done
if [[ $final ]]
then
echo "It exists at $final"
else
echo "It doesn't exist anywhere"
fi

Counting All FIles/Directories in a Specified Directory - bash/shell scripting

The finished product is meant to recursively count everything in a specified directory, or the current if no arguments are entered. Right now Im just trying to get it to count anything in the specified directories. I'm having difficulty getting the last statements to count anything at all.
It will echo 0 files in the directory.
Could anyone give me any tips? I'm still a beginner so take it easy on me, thanks!
#!/bin/bash
#A shell script program that counts recursively how many directories/files exist in a given directory.
declare -i COUNT=0
declare -i COUNT2=0
#The script will treat COUNT as an integer that is 0 until modified.
if [ "$#" -eq "0" ]
then
for i in *
do
((COUNT++))
done
((COUNT--)) #This is done because there is always an overcount of 1.
echo "There are $COUNT files and/or directories in the current directory here."
fi
if [[ -d $1 ]]
then
for i in $1
do
((COUNT++))
done
((COUNT--)) #This is done because there is always an overcount of 1.
echo "There are $COUNT files and/or directories in $1."
fi
if [[ -d $2 ]]
then
for i in $2
do
((COUNT2++))
done
((COUNT2--)) #This is done because there is always an overcount of 1.
echo "There are $COUNT2 files and/or directories in $2."
fi
exit 0
First of, you can do what you want with a one-liner:
find . | wc -l
find . means "search in the current directory and all subdirectories". Since there is no other argument, it will simple list everything. Then, I use a pipe and wc, which stands for "word count". The -l option means "output only the number of lines".
Now, for your code, here are some tips. First, I don't really understand why you repeat your code three times (for 0, $1 and $2). You could simply do:
dir="$1"
if [ -z "$dir" ]; then dir="."; fi
You store the value of the command-line argument in $dir and if none is provided, (-z means "is empty"), you assign a default value to dir.
for i in $1 won't work if $1 is the path to a directory. So instead, you can use
for i in $(ls $dir)
Also, in your code, you don't count recursively. Is it voluntary or you don't know how to proceed ?

Problems with BASH variable multiplication inside if statment

I am having an issue getting BASH to update a variable in a piece of scripting that I am working on. Below is an excerpt from my script that I have having troubles with
read -p "Did you plan on running the server from a Ramdisk?(y/n)" RAMDISK
if [[ "$RAMDISK" == [yY] ]]; then
read -p "What is the full path to where you would like to create the ramdisk?(/var/RAMDISK)" RAMDIR
read -p "How big did you want the ramdisk to be?(2048)" RAMSIZE
if [[ "$RAMSIZE" -lt 1024 ]]; then
$NEWRAMSIZE = $((RAMSIZE*1024)) #FIXME
echo $NEWRAMSIZE
fi
RAMDISK="Enabled"
fi
if [[ "$RAMDISK" == [nN] ]]; then
RAMDISK="Disabled"
fi
echo $NEWRAMSIZE
My problem is that no matter what I am trying, the RAMSIZE variable never gets multiplied by 1024. I am trying to make it so no matter what number you enter, it will always get changed to a size in mb instead of gb, assuming anything less than 1024 is a gb size. Earlier in the script RAMSIZE defaults to 2048 and it never seems to be changed during the if statement. Please help?
I see three problems: you shouldn't have spaces around the = in an assignment, you shouldn't use $ on the variable you're assigning to ($variable is how you get the value of a variable, not how you set it), and you're using RAMSIZE in some places and NEWRAMSIZE in others. The critical lines are:
if [[ "$RAMSIZE" -lt 1024 ]]; then
RAMSIZE=$((RAMSIZE*1024)) # Note: no spaces, no extra $, same variable
echo $NEWRAMSIZE
fi
...
echo "$RAMSIZE" # Same variable
BTW, you can use shellcheck.net to spot basic problems like this.

the test -s for the "if" statement

I have a question and i would be grateful for the answer if somebody knows one.
Ok, to the point. In one of my scripts i have following expression, it is not clear for me form man page what effect it should produce:
if ! [[ -s "$the_file_to_check" ]] ; then echo "file is zero sized and not exist | is exist and zero sized | not zero sized and not exist | not zero sized or not exist | not exist (obviously zero sized)" ; fi
there exist separate check for existence (the -a key), why to add another one?
And how this logics works in anyway.
I little bit lost in definition.
P.S.
I need a check for emptiness but not existence. Thank everyone.
-s checks not only if the file exists, but also if it contains any data (that is, if it has a size greater than 0 bytes). This is more than the -a option (which is, in fact, a synonym of -e) does, which only tests if the file exists.
touch foo
[[ -a foo ]] && echo "File foo exists"
[[ -s foo ]] || echo "File foo exists, but is size 0 bytes"
(I have wondered what the rationale for -a is, since I'm not aware that it does anything different from -e.)
This if command simply prints the string file is zero sized and not exist | is exist and zero sized | not exist (obviously zero sized) if the file does not exist or if the file is zero sized.
If you want your if command to check only for the zero sized file and not file existence then you can do something like this :
if [[ $(du -h "$the_file_to_check" |cut -f 1) == "0" ]] ;then
echo "file is zero sized" ;
fi
But this if statement will post a error if file does not exist. Make sure you execute this only when the file is present.

Resources