bash file looping and passing contents to java call - bash

I have the following bash script and it isn't quite working right. The objective here is to move XMLs from /source to /active folders, then call a java script and pass in XML file contents as argument, then move active file from /active to /archive folder.
Any help is greatly appreciated!
#!/bin/bash
JAVA_HOME=/usr/lib/jvm/jdk1.6.0_02
CLASSPATH=/tracking/lib/tracking_client.jar: .
FILES=/tracking/source/*
for f in $FILES
do
filename=$(basename "$f")
cd /tracking/source/
mv /tracking/source/${filename} /tracking/active/${filename}
cd /tracking/active/
$JAVA_HOME/bin/java -cp $CLASSPATH TrackClient ## need to pass XML file contents in to java call as argument
mv /tracking/active/${filename} /tracking/archive/${filename}
done
exit 0

Use $() to insert the result of a command into the command.
$JAVA_HOME/bin/java -cp $CLASSPATH TrackClient "$(cat "/tracking/active/${filename}")"

Related

Read a file line by line and run a java program

I need to run a java program that merge multiple files with a *bam extension. the structure of the program is:
java -jar mergefiles.jar \
I=file1.bam \
I=file2.bam \
I=file3.bam \
O=output.bam
So, I am trying the run this program for all *bam files in a directory. Initially, I try to create a list with the names of the *bam files (filenames.txt)
file1.bam
file2.bam
file3.bam
and using the 'while' command, like:
while read -r line; do
java -jar MergeFiles.jar \
I=$line \
O=output.bam
done < filenames.txt
However, the program executed for each *bam file in the text file but not all together (merge only one file per time, and overwrite the output). So, how I can run the program to merge all *bam files recursively?
Also, there are other option in the bash (e.g. using a loop for) to solve this issue?
Thanks in advance.
In your question you specify that you would like to use all .bam files in a dir, so instead of creating a file with the filenames, you should probably use globbing instead. Here's an example:
#! /bin/bash
# set nullglob to be safe
shopt -s nullglob
# read the filenames into an array
files=( *.bam )
# check that files actually exist
if (( ${#files[#]} == 0 )); then echo "no files" && exit 1; fi
# expand the array with a replacement
java -jar MergeFiles.jar \
"${files[#]/#/I=}" \
O=output.bam
The problem with your current solution is that the while loop will only read one line at a time, calling the command on each line separately.

Bash error not recognizing asterisk

Hello I am trying to write a Bash Script that will loop through a directory, and run the files in that directory through a command line program.
Unfortunately when I run it I keep getting
/home/user/Documents/Original_Files/*.fastq.gz: No such file or directory
Here's my code
Origin=/home/user/Documents/Original_Files/*.fastq.gz
for a in "$Origin"
do
BASE=basename "$a"
nohup java -jar $
done
Use an array if you want to keep several values in a variable.
Origin=(/home/user/Documents/Original_Files/*.fastq.gz)
for a in "${Origin[#]}" ; do
BASE=$(basename "$a")
nohup java -jar "$BASE"...

Bash: passing a variable to mv command option

--Bash 4.1.17 (running with Cygwin)
Hello, I am trying to pass the date into the --suffix option on the move (mv) command. I am able to pass in a simple string (like my name) but unable to pass in the date. If you run the script below you will see that the mv command with the suffix="$var" works but suffix="$now" does not.
#!/bin/bash
dir="your directory goes here"
now="$(date "+%m/%d/%y")"
var="_CARL!!!"
echo "$now"
echo "$var"
cd "$dir"
touch test.txt
# error if already exists
mkdir ./stack_question
touch ./stack_question/test.txt
mv -b --suffix="$var" test.txt ./stack_question/
The idea is that if test.txt already exists when trying to move the file, the file will have a suffix appended to it. So if you run this script with:
--suffix="$var"
you will see that the stack_question directory contains two files:
test.txt & test.txt_CARL!!!
But, if you run this script with:
--suffix="$now"
you will see that in the stack_question directory only contains:
test.txt
Any help on this would be greatly appreciated!
It is because you have embedded / in your date format try
now="$(date +%m_%d_%y)"

Get `dirname $0` of a KornShell script called by a symbolic link

I have a folder organization that looks like this:
link.sh
dist/MyApp-3.0.0/script.sh
dist/MyApp-3.0.0/lib/*.jar
The link.sh is a symbolic link to the KornShell (ksh) script script.sh. In the shell script, I want to call a Java program with following command:
java -cp lib/*
When I try to launch the application from the symbolic link, I get ClassNotFound because the relative path is resolved from the link base dir (this is normal).
Inside the shell script, how can I get the full path of the script (<...>/dist/MyApp-3.0.0/)? It will allow me to modify my Java call:
java -cp ${SCRIPT_DIR}/lib/*
Edit: using readlink
You can use readlink, and it boils down to:
SCRIPT_DIR=$(dirname "$(readlink -f $0)")
Edit: without readlink
if test -h $0; then
symdir=$(dirname "$(ls -l $0 | sed -n 's/.*-> //p')")
if [[ -z $symdir ]]; then
symdir=.
fi
fullreldir=$(dirname $0)/$symdir
fi
script_dir=$(cd $fullreldir; /bin/pwd)
I misunderstood the location of the script, and had assumed that the directory of the script being invoked was in the directory structure of the target application, where the following would work:
SCRIPT_DIR=$(cd $(dirname $0); /bin/pwd)
You have to use the readlink function (man readlink)
my2c

Shell scripting debug help - Iterating through files in a directory

#!/bin/sh
files = 'ls /myDir/myDir2/myDir3/'
for file in $files do
echo $file
java myProg $file /another/directory/
done
What i'm trying to do is iterate through every file name under /myDir/myDir2/myDir3/, then use that file name as the first argument in calling a java program (second argument is "/another/directory")
When I run this script: . myScript.sh
I get this error:
-bash: files: command not found
What did I do wrong in my script? Thanks!
Per Neeaj's answer, strip off the whitespace from files =.
Better yet, use:
#!/bin/sh -f
dir=/myDir/MyDir2/MyDir3
for path in $dir/*; do
file=$(basename $path)
echo "$file"
java myProg "$file" arg2 arg3
done
Bash is perfectly capable of expanding the * wildcard itself, without spawning a copy of ls to do the job for it!
EDIT: changed to call basename rather than echo to meet OP's (previously unstated) requirement that the path echoed be relative and not absolute. If the cwd doesn't matter, then even better I'd go for:
#!/bin/sh -f
cd /myDir/MyDir2/MyDir3
for file in *; do
echo "$file"
java myProg "$file" arg2 arg3
done
and avoid the calls to basename altogether.
strip off the whitespace in and after files = as files=RHS of assignment
Remove the space surrounding the '=' : change
files = 'ls /myDir/myDir2/myDir3/'
into:
files='ls /myDir/myDir2/myDir3/'
and move the 'do' statement to its own line:
for file in $files
do
....
quote your variables and no need to use ls.
#!/bin/sh
for file in /myDir/myDir2/*
do
java myProg "$file" /another/directory/
done

Resources