Biased behavior of bash script - bash

I have 8 folders namely HCIVR5,HCIVR6,HCIVR7,HCIVR8,IVR5,IVR6,IVR7,IVR8.
I wrote down this code first
ls -d IVR* > temporary.txt
Saved this code in a file called run. then executed it using ./run. When i tried opening the file(using cat and normal opening through click), it said "cannot access temporary.txt.
This is my entire code
ls -d IVR* > temporary.txt
while read ivr_line;do echo $ivr_line;cd $ivr_line;./ivr_alarm;cd ..;done < temporary.txt
ls -d HCIVR* > temporary.txt
while read hcivr_line;do echo $hcivr_line;cd $hcivr_line;./hcivr_alarm;cd ..;done < temporary.txt
Now this program works for IVR5,6,7,8. After that i get the error
./run: line 4: temporary.txt: No such file or directory
even when i comment the first two lines i get the same error
code for ivr_alarm is this
mkdir TEMP
day=`date +%d-%m-%Y`
read ip<ip.txt
read ivr_number<ivr_number.txt
while read line;do scp -i ivr"$ivr_number"_key -r root#$ip:${line%?} ./TEMP/ ;done < files_needed.txt
mv ./TEMP/.bash_history ./LOGS/.bash_history_"$day"
cd TEMP
for file in *;do
mv $file ../LOGS/${file%.*}_"$day".${file##*.}
done
cd ..
rmdir TEMP
code for hcivr_alarm is this
day=`date +%m-%d-%Y`
read ip<ip.txt
read ivr_number<ivr_number.txt
rm alarmtest
rm ./LOGS/HEALTH_CHECK_$day.log
while read line;do
echo "ssh -i hcivr"$ivr_number"_key root#$ip '${line%?}'>>./LOGS/HEALTH_CHECK_$day.log" >> alarmtest
done < commands.txt
chmod 700 alarmtest
./alarmtest
and for alarmtest(for HCIVR5, key changes to hcivr6_key for HCIVR6 and so on) is this
ssh -i hcivr5_key root#172.19.66.137 'ocstatus'>>./LOGS/HEALTH_CHECK_04-25-2012.log
ssh -i hcivr5_key root#172.19.66.137 'ocmp-bre status'>>./LOGS/HEALTH_CHECK_04-25-2012.log
Now this program works for IVR5,6,7,8. After that i get the error
./run: line 4: temporary.txt: No such file or directory
even when i comment the first two lines i get the same error. Where am i going wrong . Because when i manually open all the HCIVR folders and run ./hcivr_alarm everything works fine

Try this:
ls -d IVR* > temporary.txt
while read ivr_line;do echo $ivr_line;pushd $ivr_line;./ivr_alarm;popd;done < temporary.txt
ls -d HCIVR* > temporary.txt
while read hcivr_line;do echo $hcivr_line;pushd $hcivr_line;./hcivr_alarm;popd;done < temporary.txt
I can't see how, but I think you're screwing up your current directory, somehow.

Related

Send files to folders using bash script

I want to copy the functionality of a windows program called files2folder, which basically lets you right-click a bunch of files and send them to their own individual folders.
So
1.mkv 2.png 3.doc
gets put into directories called
1 2 3
I have got it to work using this script but it throws out errors sometimes while still accomplishing what I want
#!/bin/bash
ls > list.txt
sed -i '/list.txt/d' ./list.txt
sed 's/.$//;s/.$//;s/.$//;s/.$//' ./list.txt > list2.txt
for i in $(cat list2.txt); do
mkdir $i
mv $i.* ./$i
done
rm *.txt
is there a better way of doing this? Thanks
EDIT: My script failed with real world filenames as they contained more than one . so I had to use a different sed command which makes it work. this is an example filename I'm working with
Captain.America.The.First.Avenger.2011.INTERNAL.2160p.UHD.BluRay.X265-IAMABLE
I guess you are getting errors on . and .. so change your call to ls to:
ls -A > list.txt
-A List all entries except for . and ... Always set for the super-user.
You don't have to create a file to achieve the same result, just assign the output of your ls command to a variable. Doing something like this:
files=`ls -A`
for file in $files; do
echo $file
done
You can also check if the resource is a file or directory like this:
files=`ls -A`
for res in $files; do
if [[ -d $res ]];
then
echo "$res is a folder"
fi
done
This script will do what you ask for:
files2folder:
#!/usr/bin/env sh
for file; do
dir="${file%.*}"
{ ! [ -f "$file" ] || [ "$file" = "$dir" ]; } && continue
echo mkdir -p -- "$dir"
echo mv -n -- "$file" "$dir/"
done
Example directory/files structure:
ls -1 dir/*.jar
dir/paper-279.jar
dir/paper.jar
Running the script above:
chmod +x ./files2folder
./files2folder dir/*.jar
Output:
mkdir -p -- dir/paper-279
mv -n -- dir/paper-279.jar dir/paper-279/
mkdir -p -- dir/paper
mv -n -- dir/paper.jar dir/paper/
To make it actually create the directories and move the files, remove all echo

why 'ls' command printing the directory content multiple times

I have the following shell script in which I want to check the specific directory content on the remote machines and print them in a file.
file=serverList.csv
n=0
while [ $n -le 2 ]
do
while IFS=: read -r f1 f2
do
# echo line is stored in $line
if echo $f1 | grep -q "xx.xx.xxx";
then
ssh user#$f1 ls path/*war_* > path/$f1.txt < /dev/null; ls path/*zip_* >> path/$f1.txt < /dev/null;
ssh user#$f1 ls -d /apps/jetty*_* >> path/$f1.txt < /dev/null;
fi
done < "$file"
sleep 15
n=$(( n+1 ))
done
I am using this script inside a cron job for every 2 minute as following:
*/2 * * * * /path/myscript.sh
but somehow I am ending up with the following output file:
/apps/jetty/webapps_wars/test_new.war
path/ReleaseTest.static.zip_2020-08-05
path/ReleaseTest.static.zip_2020-08-05
path/ReleaseTest.static.zip_2020-08-05
path/jetty_xx.xx_2020-08-05
path/jetty_new
path/jetty_xx.xx_2020-08-05
path/jetty_new
I am not sure why am I getting the files in the list twice, sometimes 3 times. but I execute the shell directly from putty, it works fine. What do I need to change in order to correct this script?
Example:
~$ cd tmp
~/tmp$ mkdir test
~/tmp$ cd !$
cd test
~/tmp/test$ mkdir -p apps/jetty/webapp_wars/ && touch apps/jetty/webapp_wars/test_new.war
~/tmp/test$ mkdir path
~/tmp/test$ touch path/{ReleaseTest.static.zip_2020-08-05,jetty_xx.xx_2020-08-05,jetty_new}
~/tmp/test$ cd ..
~/tmp$ listpath=$(find test/path \( -name "*2020-08-05" -o -name "*new" \) )
~/tmp$ listapps=$(find test/apps/ -name "*war" )
~/tmp$ echo ${listpath[#]}" "${listapps[#]} | tr " " "\n" | sort > resultfile
~/tmp$
~/tmp$ cat resultfile
test/apps/jetty/webapp_wars/test_new.war
test/path/jetty_new
test/path/jetty_xx.xx_2020-08-05
test/path/ReleaseTest.static.zip_2020-08-05
~/tmp$ rm -rf test/ && unset listapps && unset listpath && rm resultfile
~/tmp$
This way you get only one result for each pattern you are looking for in your if...then...else block of code.
Just adapt the ssh ..... find commands and take care of quotes & parentheses but there is the easiest solution, this way you do not have to rewrite the script from scratch. And be careful on local / remote variables if you use them.
You really should not use ls but the fundamental problem is probably that three separate commands with three separate wildcards could match the same file three times.
Also, one of your commands is executed locally (you forgot to put ssh etc in front of the second one), so if the wildcard matches on your local computer, that would produce a result which doesn't reflect the situation on the remote server.
Try this refactoring.
file=serverList.csv
n=0
while [ $n -le 2 ]
do
while IFS=: read -r f1 f2
do
# echo line is stored in $line <- XXX this is not true
if echo "$f1" | grep -q "xx.xx.xxx";
then
ssh user#$f1 "printf '%s\n' path/*war_* path/*zip_* /apps/jetty*_*" | sort -u >path/"$f1".txt < /dev/null
fi
done < "$file"
sleep 15
n=$(( n+1 ))
done
The sort gets rid of any duplicates. This assumes none of your file names contain newlines; if they do, you'd need to use something which robustly handles them (try printf '%s\0' and sort -z but these are not portable).
ls would definitely also accept three different wildcards but like the link above explains, you really never want to use ls in scripts.

bash move is failing

I am running below commands in a script
move_jobs() {
cd $JOB_DIR
for i in `cat $JOBS_FILE`
do
if [ `ls | grep -i ^${i}- | wc -l` -gt 0 ]; then
cd $i
if [ ! -d jobs ]; then
mkdir jobs && cd .. && mv "${i}"-* "${i}"/jobs/
else
cd .. && mv "${i}"-* "${i}"/jobs/
fi
error_handler $?
fi
done
}
but it failing as
mv: cannot stat `folder-*': No such file or directory
Not sure why move command is failing with regular expression
Your script is overly complicated and has several issues, one of which will be the problem, I guess it's the ls | grep ... part, but to find that out, you should include some debug logging.
for i in $(cat ...) loops through words, not lines.
Do not parse ls
And if you still do, do not ever grep for filenames but include it in your ls call: ls "${i}"-* | wc -l.
You do not need to check if a folder exists when the only thing that is different then is that you create it. You can use mkdir -p instead.
Jumping around folders in your script makes it almost unreadable, as you need to keep track of all cd commands when reading your script.
You could simply write the following, which I think will do what you want:
xargs -a "$JOBS_FILE" -I{} \
sh -c "
mkdir -p '$JOB_DIR/{}/jobs';
mv '$JOB_DIR/{}-'* '$JOB_DIR/{}/jobs';
"
or if you need more control:
while IFS= read -r jid; do
if ls "$JOB_DIR/$jid-"* &>/dev/null; then
TARGET_DIR="$JOB_DIR/$jid/jobs"
mkdir -p "$TARGET_DIR"
mv "$JOB_DIR/$jid-"* "$TARGET_DIR"
echo "OK"
else
echo "No files to move."
fi
done < "$JOBS_FILE"

Bash loop to read line by line and create folder by line index

I am trying to do the following in a bash file:
mybash.sh myinputfile.txt myloopfile.csv
Create a for loop, that reads myloopfile.csv line by line, and then creates a folder which will take the line number as the folder name prefixed to "folder", ex. folder1, folder2...
and then inside this folder$i create a folder called input and another called output.
write the line$i content into a file called myline.txt and put this file inside the folder$i/input
and copy the file myinputfile.txt that i will pass as a parameter to the bash file inside the folder$i/input as well.
and then run my personal script that takes two arguments:
python myscript.py -i ./folder$i/input -o ./folder$i/output
and done!
myfile.csv
101,1001,10012,100121
102,101213,11122.1,12.15
103,122.15,155.2,1515.54
104,154.4,4551.1,454
what I currently have:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
mkdir ./folder$line
echo "$line" >> Folder$line/input/myline.txt;
cp myinputfile.txt Folder$line/input
python myscript.py -i ./folder$i/input -o ./folder$i/output
done < "$1"
the problem is that I can't get the line index to pass it as a suffix to the folder name, so I currently get the line content.and I don't know how to read the two files from the arguments that i pass to the mybash.sh.
Use a counter to keep track of line numbers:
#!/bin/bash
input_file=$1
csv_file=$2
count=1
while IFS= read -r line || [[ -n "$line" ]]; do
input_dir="./folder$count/input"
output_dir="./folder$count/output"
mkdir -p "$input_dir" "$output_dir"
printf '%s\n' "$line" > "$input_dir/myline.txt"
cp "$input_file" "$input_dir"
python myscript.py -i "$input_dir" -o "$output_dir"
((count++))
done < "$csv_file"

what is the purpase of the command rsync -rvzh

im trying to understand what this two command doing:
config=$(date +%s)
rsync -rvzh $1 /var/lib/tomcat7/webapps/ROOT/DataMining/target > /var/lib/tomcat7/webapps/ROOT/DataMining/$config
this line appears in a bigger script - script.sh looking like this:
#! /bin/bash
config=$(date +%s)
rsync -rvzh $1 /var/lib/tomcat7/webapps/ROOT/DataMining/target > /var/lib/tomcat7/webapps/ROOT/DataMining/$config
countC=0
countS=`wc -l /var/lib/tomcat7/webapps/ROOT/DataMining/$config | sed 's/^\([0-9]*\).*$/\1/'`
let countS--
let countS--
let countS--
while read LINEC #read line
do
if [ "$countC" -gt 0 ]; then
if [ "$countC" -lt "$countS" ]; then
FILENAME="/var/lib/tomcat7/webapps/ROOT/DataMining/target/"$LINEC
count=0
countW=0
while read LINE
do
for word in $LINE;
do
echo "INSERT INTO data_mining.data (word, line, numWordLine, file) VALUES ('$word', '$count', '$countW', '$FILENAME');" >> /var/lib/tomcat7/webapps/ROOT/DataMining/query
mysql -u root -Alaba1515< /var/lib/tomcat7/webapps/ROOT/DataMining/query
echo > /var/lib/tomcat7/webapps/ROOT/DataMining/query
let countW++
done
countW=0
let count++
done < $FILENAME
count=0
rm -f /var/lib/tomcat7/webapps/ROOT/DataMining/query
rm -f /var/lib/tomcat7/webapps/ROOT/DataMining/$config
fi
fi
let countC++
done < /var/lib/tomcat7/webapps/ROOT/DataMining/$config #finish while
i was able to find lots of documentary about rsync and what it is doing but i don't understand whats the rest of the command do. any help please?
The first command assigns the current time (in seconds since epoch) to the shell variable config. For example:
$ config=$(date +%s)
$ echo $config
1446506996
rsync is a file copying utility. The second command thus makes a backup copy of the directory listed in argument 1 (referred to as $1). The backup copy is placed in /var/lib/tomcat7/webapps/ROOT/DataMining/target. A log file of what was copied is saved in var/lib/tomcat7/webapps/ROOT/DataMining/$config:
rsync -rvzh $1 /var/lib/tomcat7/webapps/ROOT/DataMining/target > /var/lib/tomcat7/webapps/ROOT/DataMining/$config
The rsync options mean:
-r tells rsync to copy files diving recursively into subdirectories
-v tells it to be verbose so that it shows what is copied.
-z tells it to compress files during their transfer from one location to the other.
-h tells it to show any numbers in the output in human-readable format.
Note that because $1 is not inside double-quotes, this script will fail if the name of directory $1 contains whitespace.

Resources