Weird issue with "sed" command - linux

On my script, this -for unknown some reason- gives me errors when it reaches sed command:
function nzb() {
( [ -z "$1" ] ) && echo "No argument is given!" && return 1
hash="$(echo -n "$1" | md5sum | cut -d" " -f1)"
mkdir "${hash}" && rar a -m0 -v200M "${hash}"/"${hash}".rar "$1" && rm -rf "$1" &&
par2 c -r10 -l "${hash}"/"${hash}".par2 "${hash}"/* && ~/newsmangler-master/mangler.py
-c ~/.newsmangler.conf "{hash}" && sed -i "1i$1\n${hash}\n" ~/hashs.txt
}
.
ERROR: "{hash}" does not exist or is not a file!
ERROR: no valid arguments provided on command line!
But when I -out of curiosity- removed sed's preceding commands, it worked perfectly like it suppose to:
function nzb() {
( [ -z "$1" ] ) && echo "No argument is given!" && return 1
hash="$(echo -n "$1" | md5sum | cut -d" " -f1)"
sed -i "1i$1\n${hash}\n" ~/hashs.txt
}
.
Any Ideas?
EDIT: it seems the problem is located in this area:
. . . && ~/newsmangler-master/mangler.py -c ~/.newsmangler.conf "{hash}" && . . .
Because even this is working:
function nzb() {
( [ -z "$1" ] ) && echo "No argument is given!" && return 1
hash="$(echo -n "$1" | md5sum | cut -d" " -f1)"
mkdir "${hash}" && rar a -m0 -v200M "${hash}"/"${hash}".rar "$1" && rm -rf "$1" &&
par2 c -r10 -l "${hash}"/"${hash}".par2 "${hash}"/* && sed -i "1i$1\n${hash}\n"
~/hashs.txt
}

Replace "{hash}" with "${hash}"

Related

Downloading/Buidling minecraft server jars using BuildTools in Bash/Shell script

I am trying to write a bash/shell script for downloading BuildTools and compiling the jars with it, after that I want to move them to my webserver (/var/www/html/jars/) from within the script at /home/buildtools/
BuildTools downloads/compiles the jars and places them at the base directory, except the vanilla jar, which is located at work/ inside the base directory.
Even though it does download/compile the jars, they aren't all moving to the desired directories.
This is the code I am using at the moment (I think it might all be relevant to provide):
directory="$(pwd)/"
jar="BuildTools.jar"
path="${directory}${jar}"
output="/var/www/html/jars"
version=$1
if [[ ( -d "BuildData" ) || ( -d "Spigot" ) || ( -d "CraftBukkit" ) || ( -d "Bukkit" ) || ( -d "work" ) || ( -d "apache-maven-*" ) || ( -f "BuildTools.log.txt" ) ]]; then
echo "Cleaning up..."
rm -f -r BuildData/ Spigot/ CraftBukkit/ Bukkit/ work/ apache-maven-*/
rm -f BuildTools.log.txt spigot-*.jar craftbukkit-*.jar vanilla-*.jar
fi
if [[ ! -f "${jar}" ]]; then
echo "Downloading BuildTools..."
wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar -O ${jar}
chmod 775 ${jar}
fi
if [[ ! -z "${version}" ]]; then
echo "Compiling jars for version ${version}..."
java -jar ${jar} --rev ${version}
else
echo "No version specified."
echo "Compiling jars for the latest version..."
java -jar ${jar} --rev latest
fi
if [[ ( -f "${directory}spigot-*.jar" ) || ( -f "${directory}craftbukkit-*.jar" ) ]]; then
echo "Compilation is done. Re-organizing..."
if [[ ! -z "${version}" ]]; then
mv work/minecraft_server.*.jar ${directory}/vanilla-${version}.jar
else
mv work/minecraft_server.*.jar ${directory}/vanilla-latest.jar
fi
echo "Moving jars to the webserver..."
mv ${directory}/vanilla-*.jar ${output}/
mv ${directory}/spigot-*.jar ${output}/
mv ${directory}/craftbukkit-*.jar ${output}/
else
echo "Could not re-organize, the jars hasn't been moved."
fi
Edit:
By executing the command: ./compile.sh 1.8.6
For some reason the jarfiles aren't the right names.
Result of the code.
directory="$(pwd)/"
jar="BuildTools.jar"
path="${directory}${jar}"
output="/var/www/html/jars"
version=$1
if [[ ( -d "BuildData" ) || ( -d "Spigot" ) || ( -d "CraftBukkit" ) || ( -d "Bukkit" ) || ( -d "work" ) || ( -d "apache-maven-*" ) || ( -f "BuildTools.log.txt" ) ]]; then
echo "Cleaning up..."
rm -f -r BuildData/ Spigot/ CraftBukkit/ Bukkit/ work/ apache-maven-*/
rm -f BuildTools.log.txt done.txt spigot-*.jar craftbukkit-*.jar vanilla-*.jar
fi
if [[ ! -f "${jar}" ]]; then
echo "Downloading BuildTools..."
wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar -O ${jar}
chmod 775 ${jar}
fi
if [[ ! -z "${version}" ]]; then
echo "Compiling jars for version ${version}..."
java -jar ${jar} --rev ${version}
echo "done" > done.txt
else
echo "No version specified. Compiling jars for the latest version..."
java -jar ${jar} --rev latest
echo "done" > done.txt
fi
if [[ -f "done.txt" ]]; then
echo "Compilation is done. Re-organizing..."
for x in $(find ${directory} \( -name "*.jar" \)); do
name=$(basename "${x}" ".jar")
if [[ ${name} =~ ^(spigot|craftbukkit|minecraft_server)(-)?(.*)? ]]; then
fullname="${name}.jar"
echo "Jar found: ${fullname}, Moving to webserver..."
if [[ ! -z "${version}" ]]; then
outpath=${output}/${version}
if [[ ! -d ${outpath} ]]; then
mkdir ${outpath}
fi
mv -f ${x} ${outpath}/${fullname}
else
outpath=${output}/latest
if [[ ! -d ${outpath} ]]; then
mkdir ${outpath}
fi
rm -f -r ${outpath}
mv -f ${x} ${outpath}/${fullname}
fi
fi
done
echo "Jars uploaded."
else
echo "Could not re-organize, the jars hasn't been moved."
fi
And additionally, I would like to only have one file of each uploaded (Vanilla, Spigot, Craftbukkit), how do I do that?
It's because of the parenthesis inside your conditional expression, as well as trying to use globs on the wrong part of the expression (you can't use tests like that with globs).
To fix this you should do something like:
#set nullglob so non-matching globs return an empty string instead of an error
shopt -s nullglob
# assing the globs to arrays, note the quoting
spigotfiles=("${directory}"spigot-*.jar)
bukkitfiles=("${directory}"craftbukkit-*.jar)
# using an array without an index gives us the first item in the array
if [[ -f "$spigotfiles" || -f "$bukkitfiles" ]]; then
...
fi
The same error with parenthesis is in your cleanup-code too, which you can handle by just removing the parens (e.g. [[ -d "dirname" || -d "fooname" ]] )
You should also quote your variable expansions (i.e. "${jar}" etc.) in every case (like in a part of a command).
Also using [[ ! -z $foo ]] is the same as [[ -n $foo ]]
Edit:
Don't do
for x in $(find ${directory} \( -name "*.jar" \)); do
but instead just:
for x in *.jar; do
or if you want only your versioned files, you can do:
for x in *"-${version}.jar"; do
You still have the parens in the cleanup check, see the answer above for that.
And in the end of the script these lines are counterproductive:
if [[ ! -d ${outpath} ]]; then
mkdir ${outpath}
fi
rm -f -r ${outpath}
mv -f ${x} ${outpath}/${fullname}
As you first create a dir, then remove it and then try to move things into it (hint: remove the rm line)

Recycle Bin in Bash Script

I am trying to create a basic recycle bin concept in a VM using bash scripting. It will need to delete files that have been entered and place them into a directory that is created and save the path(origin) to a log file to be later used in a restore function.
I will start off with my delete/recycle code which I believe works just fine but seems kind of untidy/contains redundant code:
#!/bin/sh
if [ ! -d ~/recycle ]
then mkdir ~/recycle
fi
if [ ! -d ~/recycle/recycle_log ]
then mkdir ~/recycle/recycle_log
fi
if [ ! -d ~/recycle/recycle_bin ]
then mkdir ~/recycle/recycle_bin
fi
if [ -d ~/recycle ]
then
echo "$(readlink -f "$1")" >> "$HOME/recycle/recycle_log/log_file" && mv "$1" "$HOME/recycle/recycle_bin"
echo "$(readlink -f "$2")" >> "$HOME/recycle/recycle_log/log_file" && mv "$2" "$HOME/recycle/recycle_bin"
echo "$(readlink -f "$3")" >> "$HOME/recycle/recycle_log/log_file" && mv "$3" "$HOME/recycle/recycle_bin"
echo "$(readlink -f "$4")" >> "$HOME/recycle/recycle_log/log_file" && mv "$4" "$HOME/recycle/recycle_bin"
fi
#end
Thereafter what I have for my restore script is as follows:
#!/bin/sh
cd "$HOME/recycle/recycle_bin" || exit 1
mv -i "$(grep "$1" "$HOME/recycle/recycle_log")"
I imagine this is somewhat close to what I need to return any deleted file stored in the log/recycle bin to be restored to its origin but the error I am getting is:
mv: missing destination file operand after `'
Any thoughts on where I'm going wrong?
Try this:
recycle.sh
#!/bin/sh
set -e
check_dir() {
[ ! -d $1 ] || return 0
mkdir --parents $1
}
check_dir "${HOME}/recycle/recycle_bin"
touch "${HOME}/recycle/recycle_log"
for file in "$#"; do
echo "$(readlink -f "$file")" >> "${HOME}/recycle/recycle_log"
mv "$file" "${HOME}/recycle/recycle_bin"
done
#end
restore.sh
#!/bin/sh
set -e
cd "${HOME}/recycle/recycle_bin" || exit 1
for name in "$#"; do
file=$(grep "\/${name}\$" "${HOME}/recycle/recycle_log")
mv -i $name "$file"
sed -i "/\/${name}\$/ d" "${HOME}/recycle/recycle_log"
done
Some insights:
set -e: Abort on any error, to avoid some if's
$#: The array of arguments ($1, $2...)
[ ! -d $1 ] || return 0: Since we are using set -e, do not fail if the directory exists
grep "\/${name}\$" ...: Only matches the name at the end of the path
sed -i: sed in-place editing to remove the line

Chained && and || operators in bash scripting

I want to execute a series of commands in a bash script.
If any fail, the script should echo a line describing which line failed, and then exit the function.
Currently, my script echos the output adequately, but doesn't exit the script (because the echo command returns 0).
I have
COMMAND_A || echo "command A failed" | tee -a $SUMMARY_FILE
COMMAND_B || echo "command B failed" | tee -a $SUMMARY_FILE
COMMAND_C || echo "command C failed" | tee -a $SUMMARY_FILE
but these have no dependence on the previous line - I think enclosing with bash -e would also not help, since then either COMMAND_A failing would exit without the echo, or else the echo would succeed and nothing would exit.
Since the echo will succeed, I can't just add && to each line.
I could perhaps use
{ COMMAND_A && \
{ COMMAND_B && \
{ COMMAND_C || echo "C failed" | tee -a $SUM } \
|| echo "B failed" | tee -a $SUM } \
|| echo "A failed" | tee -a $SUM }
but this seems very clunky.
Is there a better syntax/style/method?
For a concrete example:
cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=Release .. || \
echo "$(date +%d/%m/%y-%H:%M:%S): cmake failed for $1" | tee -a $SUMFILE
make -j16 || \
echo "$(date +%d/%m/%y-%H:%M:%S): make failed for $1" | tee -a $SUMFILE
sudo make install && \
echo "$(date +%d/%m/%y-%H:%M:%S): Installed $1" | tee -a $SUMFILE || \
echo "$(date +%d/%m/%y-%H:%M:%S): make install failed for $1" | tee -a $SUMFILE
Edit
I can perhaps get some improvement with
COMMAND_A || { echo "A failed" && false; } && \
COMMAND_B || { echo "B failed" && false; } && \
COMMAND_C && echo "C succeeded" || { echo "C failed" && false; }
but this will still print that A, B and C failed if A fails (even though the commands are short-circuited, hence the improvement)
Since the series of commands is executed within a function, the return statement can be used.
If this were not the case, exit may be the appropriate choice.
Consequently, I can use the idea in the question's edit to write:
standardInstall() {
# Should be passed the directory (ie application/library) name as
# an argument.
if [ -z "$1" ]; then
echo "No argument was passed to standardInstall()"
echo "Exiting"
exit 2
fi
pushd $1/build/
cmake -DCMAKE_INSTALL_PREFIX=$KF5 -DCMAKE_BUILD_TYPE=Release .. || \
{ echo "$(date +%d/%m/%y-%H:%M:%S): cmake failed for $1" \
| tee -a $SUMFILE && return 1; } && \
make -j16 || \
{ echo "$(date +%d/%m/%y-%H:%M:%S): make failed for $1" \
| tee -a $SUMFILE && return 1; } && \
sudo make install && \
echo "$(date +%d/%m/%y-%H:%M:%S): Installed $1" | tee -a $SUMFILE || \
{ echo "$(date +%d/%m/%y-%H:%M:%S): make install failed for $1" \
| tee -a $SUMFILE && return 1; }
popd
}

Shell script randomly fails to execute file operations commands

I'm having a bit of trouble running this script. Every now and then, it will fail to execute a mv command or rm command referenced below. Then the next iteration will feel the full repercussions of that failure. Why is this happening, and how do I control for it? For reference, the syntax phyml -i $f [parameters] outputs the files $f_phyml_tree.txt and $f_phyml_stats.txt into the same directory as $f. I want to get both these files out of that directory while saving the tree somewhere else.
ber="_phyml_tree.txt"
for f in ~/randseqs/aa/*.txt;
do
echo $f
fpath=`echo $f | cut -d'/' -f 6`
if [ ! -f /home/mcb3421_10/phymlout/aa/$fpath$ber ] || [ ! -f /home/mcb3421_10/phymltimer/aa/$fpath ]; then
phyml -i $f -d aa -b 0 -m Blosum62 > ~/blown.txt
grep "Time used" < ~/blown.txt > ~/phymltimer/aa/$fpath
mv /home/mcb3421_10/randseqs/aa/*$ber phymlout/aa
if [ ! -f /home/mcb3421_10/phymlout/aa/$fpath$ber ]; then
echo $f failed to write, check the logfile /home/mcb3421_10/phymllogs/aa/$fpath
fi
rm ~/randseqs/aa/*_stat*
mv ~/blown.txt ~/phymllogs/aa/$fpath
fi
done
for f in ~/randseqs/nuc/*.txt;
do
echo $f
fpath=`echo $f | cut -d'/' -f 6`
if [ ! -f /home/mcb3421_10/phymlout/nuc/$fpath$ber ] || [ ! -f /home/mcb3421_10/phymltimer/nuc/$fpath ]; then
phyml -i $f -d nt -b 0 -m HKY85 > ~/blown.txt
grep "Time used" < ~/blown.txt > ~/phymltimer/nuc/$fpath
mv /home/mcb3421_10/randseqs/nuc/*$ber phymlout/nuc
if [ ! -f /home/mcb3421_10/phymlout/nuc/$fpath$ber ]; then
echo $f failed to write, check the logfile /home/mcb3421_10/phymllogs/nuc/$fpath
fi
rm ~/randseqs/nuc/*_stat*
mv ~/blown.txt ~/phymllogs/nuc/$fpath
fi
done

Incorrect results from Md5 sum in bash shell script

I'm missing some images that should have been archived when this script runs. I think this may be to do with my indentations or my Md5 sum. I have tried everything I can think of.
here is the code with out the correct indentations:
#!/bin/sh
if [ ! -d "$1" ]; then
echo Directory "$1" cannot be found. Please try again.
exit
fi
if [ $# -eq 1 ]; then
echo "usage: Phar image_path archive_path"
exit
fi
if [ -d "$2" ]; then
echo "archive exists"
else
echo "the directory 'archive' does't exist. Creating directory 'archive'."
mkdir -p ~/archive
fi
find $1 -iname "IMG_[0-9][0-9][0-9][0-9].JPG" | cat > list.txt
[ -f ~/my-documents/md5.txt ] && rm md5.txt || break
while read line;
do md5sum $line | xargs >> md5.txt
done < list.txt
sort -k 1,1 -u md5.txt | cat > uniquemd5.txt
cut -d " " -f 2- uniquemd5.txt > uniquelist.txt
sort uniquelist.txt -r -o uniquelist.txt
for line in $(cat uniquelist.txt)
do
file=$(basename $line) path="$2/file"
if [ ! -f $path ];
then
cp $line $2
else
cp $line $path.JPG
fi
rm uniquelist.txt md5.txt uniquemd5.txt list.txt
done
This loop
while read line;
do md5sum $line | xargs >> md5.txt
done < list.txt
should probably be
while read line;
do md5sum "$line"
done < list.txt > md5.txt
Quote parameter expansions, and it's unclear why you needed.

Resources