Convert Bash script to Perl/VBS/any other windows compatible language [closed] - perl

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I got a bash script that was made for transferring files from a Sandbox to a host.
The files in the sandboxdirectory get transferred only if they are younger, meaning they have been "touched" before. Unfortunately, cygwin is causing trouble under windows so I need the script in another language or I need something that works like cygwin under windows.
The script is just about 20 lines, but i don't have any clue how to convert it to another language(especially commands like touch, make, gcc, getopts, set -e)
I'd be happy if someone finds this easy to do and converts it:
# EXITING SCRIPT IF ERROR OCCURS
set -e
FORCE=false
JUSTPRINT=
# if parameter -f is given, force to transfer all files(no matter if new or not)
# if -n is given checking files
while getopts fn opt 2>/dev/null
do
case $opt in
f) FORCE=true ;;
n) JUSTPRINT="-n" ;;
?) ;;
esac
done
# deleting parsed options from command line
shift `expr $OPTIND - 1`
# refresh files that came with -f
if [ \( $FORCE = true \) -a \( $# -gt 0 \) ]
then
touch -c $#
fi
# Targets (dummy files for timestamp)
TARGETS=`for filename
do
if [ -f $filename ]
then
echo "../transport_dummies/\`basename $filename\`.dum"
else
echo "$filename"
fi
done`
# call script directory
echo $0
cd `dirname $0`
# creating sysfilterL.exe
if [ ! -f sysfilterL ]
then
echo "sysfilterL is created."
gcc sysfilter.c -o sysfilterL
fi
# Call Transport-Makefile with target
if [ $# -gt 0 ]
then
make --warn-undefined-variables $JUSTPRINT -f transportDE.mk reset $TARGETS
send_queueed
else
make --warn-undefined-variables $JUSTPRINT -f transportDE.mk
fi

You can convert the shell script to a batch file, which is covered here: How do I convert a bash shell script to a .bat file?
Also here is a list of corresponding commands in bash and batch: http://tldp.org/LDP/abs/html/dosbatch.html

Related

KSH : Display Wait message while processing a command

I'm trying to display a message (with simple echo) like "Processing" which would go "Processing.", "Processing..", "Processing...", then go back the other way, and again, and again... until a command finish executing.
The command I'm trying to do that on is a simple git clone on a branch with 'quiet' parameter, looks like this :
git clone --quiet -b dev src_path dest_path >/dev/null
The idea is that, no matter the number of points after "Processing" (1, 2 or 3), it stops displaying when the process ends.
Don't know if there is a native way to do this, or if this is pretty hard to do, but I'm kind of new in KSH scripting so will not understand too complex stuff (plus i'm not english fluent)
Thanks for your answers !
Edit : Finally found a way to do it, maybe a little longer than what I was expecting for but since it doesn't seems to be a native way helping for this, that's pretty correct. Here's what I did (thanks to markp-fuso who helped with his keywords).
git clone --quiet -b dev src_path dest_path >/dev/null &
PROC_ID=$!
NB=0
WAY=1
while kill -0 "$PROC_ID" >/dev/null; do
if [ $WAY = 1 ]; then
if [ $NB = 2 ];then
WAY=0
fi
NB=$((NB+1))
else
if [ $NB = 2 ];then
WAY=1
fi
NB=$((NB-1))
fi
echo -ne "Processing"
i=1
while [ i -lt $((NB+1)) ]; do
echo -ne "."
i=$((i+1))
done
echo -ne " \r"
sleep 0.5
done
clear
echo -ne "Process complete.\n"
Note that I had to add a clear command at the end of the while loop because once the git clone is complete, the loop returns a warning saying the process doesn't exist (anymore). So I clear right after the warning displays to let it invisible for th user. If you find a way to catch it, you're welcome ! Really surprised that it displays even with the /dev/null statement.
You can adapt this strategy:
print -n "Processing"
while true; do
print -n "."
sleep 5
done

Bourne Shell Script

I'm attempting to write a script in the Bourne shell that will do the following:
Read in a filename
If the file does not exist in the target directory, it will display a message to the user stating such
If the file exists in the target directory, it will be moved to a /trash folder
If the file exists in the target directory, but a file of the same name is in the /trash folder, it will still move the file to the /trash directory, but will attach a _bak extention to the file.
My use of the Bourne shell is minimal, so here's what I have so far. Any pointers or tips would be greatly appreciated, thanks!
#!/bin/sh
#Scriptname: Trash Utility
source_dir=~/p6_tmp
target_dir=~/trash
echo "Please enter the filename you wish to trash:"
read filename
if [ -f $source_dir $filename]
then mv "$filename" "$target_dir"
else
echo "$filename does not exist"
fi
You cannot use ~ to refer to $HOME in a sh script. Switch to $HOME (or change the shebang to a shell which supports this, such as #!/bin/bash).
To refer to a file in a directory, join them with a slash:
if [ -f "$source_dir/$filename" ]
Notice also the required space before the terminating ] token.
To actually move the file you tested for, use the same expression for the source argument to mv:
mv "$source_dir/$filename" "$target_dir"
As a general design, a script which takes a command-line parameter is much easier to integrate into future scripts than one wich does interactive prompting. Most modern shells offer file name completion and history mechanisms, so a noninteractive script also tends to be more usable (you practically never need to transcribe a file name manually).
A Bash Solution:
#!/bin/bash
source_dir="~/p6_tmp"
target_dir="~/trash"
echo "Please enter the filename you wish to trash:"
read filename
if [ -f ${source_dir}/${filename} ]
then
if [ -f ${target_dir}/${filename} ]
then
mv "${source_dir}/${filename}" "${target_dir}/${filename}_bak"
else
mv "${source_dir}/${filename}" "$target_dir"
fi
else
echo "The file ${source_dir}/${filename} does not exist"
fi
Here's the completed script. Thanks again to all who helped!
#!/bin/sh
#Scriptname: Trash Utility
#Description: This script will allow the user to enter a filename they wish to send to the trash folder.
source_dir=~/p6_tmp
target_dir=~/trash
echo "Please enter the file you wish to trash:"
read filename
if [ -f "$source_dir/$filename" ]
then
if [ -f "$target_dir/$filename" ]
then mv "$source_dir/$filename" "$target_dir/$(basename "$filename")_bak"
date "+%Y-%m-%d %T - Trash renamed ~/$(basename "$source_dir")/$filename to ~/$(basename "/$target_dir")/$(basename "$filename")_bak" >> .trashlog
else mv "$source_dir/$filename" "$target_dir"
date "+%Y-%m-%d %T - Trash moved ~/$(basename "/$source_dir")/$filename to ~/$(basename "/$target_dir")/$filename" >> .trashlog
fi
else
date "+%Y-%m-%d %T - Trash of ~/$(basename "/$source_dir")/$filename does not exist" >> .trashlog
fi

comparing two directories with separate diff output per file

I'd need to see what has been changed between two directories which contain different version of a software sourcecode. While I have found a way to get a unique .diff file, how can I obtain a different file for each changed file in the two directories? I'd need this, as the "main" is about 6 MB and wanted some more handy thing.
I came around this problem too, so I ended up with some lines of a shell script. It takes three arguments: Source and destination directory (as used for diff) and a target folder (should exist) for the output.
It's a bit hacky, but maybe it would be useful for someone. So use with care, especially if your paths have special characters.
#!/bin/sh
DIFFARGS="-wb"
LANG=C
TARGET=$3
SRC=`echo $1 | sed -e 's/\//\\\\\\//g'`
DST=`echo $2 | sed -e 's/\//\\\\\\//g'`
if [ ! -d "$TARGET" ]; then
echo "'$TARGET' is not a directory." >&2
exit 1
fi
diff -rqN $DIFFARGS "$1" "$2" | sed "s/Files $SRC\/\(.*\?\) and $DST\/\(.*\?\) differ/\1/" | \
while read file
do
if [ ! -d "$TARGET/`dirname \"$file\"`" ]; then
mkdir -p "$TARGET/`dirname \"$file\"`"
fi
diff $DIFFARGS -N "$1/$file" "$2/$file" > "$TARGET"/"$file.diff"
done
if you want to compare source code it is better to commit it to a source vesioning program as "svn".
after you have done so. do a diff of your uploaded code and pipe it to file.diff
svn diff --old svn:url1 --new svn:url2 > file.diff
A bash for loop will work for you. The following will diff two directories with C source code and produce a separate diff for each file.
for FILE in $(find <FIRST_DIR> -name '*.[ch]'); do DIFF=<DIFF_DIR>/$(echo $FILE | grep -o '[-_a-zA-Z0-9.]*$').diff; diff -u $FILE <SECOND_DIR>/$FILE > $DIFF; done
Use the correct patch level for the lines starting with +++

Get current playing file in MPlayer slave mode

Problem: I can't find any way to reliably get the current playing file in an MPlayer playlist.
Here is how far I have gotten. This working ash script monitors a text file with the path to the current playlist. When I update the file, the script closes the old instance of MPlayer and opens a new one with the new playlist:
# POLL PLAYLIST FILE FOR CHANGES
CURRENTPLAYLISTPATH=/home/tc/currentplaylist
INFIFO=/tmp/mplayer-in
CURRENTPLAYLIST="NEVERMATCHAPLAYLIST"
FIRSTRUN=1
while [ 1 ];
do
# CHECK FOR NEW PLAYLIST
NEWPLAYLIST=$(head -n 1 $CURRENTPLAYLISTPATH)
if [[ "$NEWPLAYLIST" != "$CURRENTPLAYLIST" ]]; then
if [ "$FIRSTRUN" == 0 ]; then
echo "quit" > "$INFIFO"
fi
# CREATE NAMED PIPE, IF NEEDED
trap "rm -f $INFIFO" EXIT
if [ ! -p $INFIFO ]; then
mkfifo $INFIFO
fi
# START MPLAYER
mplayer -fixed-vo -nolirc -vc ffmpeg12vdpau,ffh264vdpau, -playlist $NEWPLAYLIST -loop 0 -geometry 1696x954 -slave -idle -input file=$INFIFO -quiet -msglevel all=0 -identify | tee -a /home/tc/mplayer.log &
CURRENTPLAYLIST=$NEWPLAYLIST
FIRSTRUN=0
fi
sleep 5;
done
My original plan was just to use the "-identify" flag and parse the log file. This actually works really well up until I need to truncate the log file to keep it from getting too large. As soon as my truncating script is run, MPlayer stops writing to the log file:
FILENAME=/home/tc/mplayer.log
MAXCOUNT=100
if [ -f "$FILENAME" ]; then
LINECOUNT=`wc -l "$FILENAME" | awk '{print $1}'`
if [ "$LINECOUNT" -gt "$MAXCOUNT" ]; then
REMOVECOUNT=`expr $LINECOUNT - $MAXCOUNT`
sed -i 1,"$REMOVECOUNT"d "$FILENAME"
fi
fi
I have searched and searched but have been unable to find any other way of getting the current playing file that works.
I have tried piping the output to another named pipe and then monitoring it, but only works for a few seconds, then MPlayer completely freezes.
I have also tried using bash (instead of ash) and piping the output to a function like the following, but get the same freezing problem:
function parseOutput()
{
while read LINE
do
echo "get_file_name" > /tmp/mplayer-in
if [[ "$LINE" == *ANS_FILENAME* ]]
then
echo ${LINE##ANS_FILENAME=} > "$CURRENTFILEPATH"
fi
sleep 1
done
}
# START MPLAYER
mplayer -fixed-vo -nolirc -vc ffmpeg12vdpau,ffh264vdpau, -playlist $NEWPLAYLIST -loop 0 -geometry 1696x954 -slave -idle -input file=/tmp/mplayer-in -quiet | parseOutput &
I suspect I am missing something very obvious here, so any help, ideas, points in the right direction would be greatly appreciated.
fodder
Alright then, so I'll post mine too.
Give this one a try (assuming there is only one instance running, like on fodder's machine):
basename "$(readlink /proc/$(pidof mplayer)/fd/* | grep -v '\(/dev/\|pipe:\|socket:\)')"
This is probably the safer way, since the file descriptors might not always be in the same order on all systems.
However, this can be shortened, with a little risk:
basename "$(readlink /proc/$(pidof mplayer)/fd/*)" | head -1
You might probably like to install this, too:
http://mplayer-tools.sourceforge.net/
Well, I gave up on getting the track from MPlayer itself.
My 'solution' is probably too hackish, but works for my needs since I know my machine will only ever have one instance of MPlayer running:
lsof -p $(pidof mplayer) | grep -o "/path/to/my/assets/.*"
If anyone has a better option I'm certainly still interested in doing this the right way, I just couldn't make any of the methods work.
fodder
You can use the run command.
Put this in ~/.mplayer/input.conf:
DEL run "echo ${filename} ${stream_pos} >> /home/knarf/out"
Now if you press the delete key while playing a file it will do what you expect i.e. append the current file playing and the position in the stream to the ~/out file. You can replace echo with your program.
See slave mod docs for more info (Ctrl-F somevar).
About getting properties from MPlayer
I have used a non-elegant solution, but it is working for me.
stdbuf -oL mplayer --slave --input=file=$FIFO awesome_awesome.mp3 |
{
while IFS= read -r line
do
if [[ "${line}" == ANS_* ]]; then
echo "${line#*=}" > ${line%=*} # echo property_value > property_name
fi
done
} &
mplayer_pid=&!
read filename < ./ANS_FILENAME
read timeLength < ./ANS_LENGTH
echo ($timeLength) $filename
and so on..
It is in another proccess, that's why I've used files to bring properties
'stdbuf' is for not to miss anything
I started putting together a bash library to handle tasks like this. Basically, you can accomplish this by dumping the mplayer output to a file. Then you grep that dump for "Playing " and take the last result with tail. This should give you the name of the file that's currently playing or that last finished playing.
Take a look at my bash code. You'll want to modify the playMediaFile function to your needs, but the getMediaFileName function should do exactly what you're asking. You'll find the code on my github.

How can I make a shell script indicate that it was successful?

If I have a basic .sh file containing the following script code:
#!/bin/sh
rm -rf "MyFolder"
How do I make this running script file display results to the terminal that will indicate if the directory removal was successful?
You don't really need to make it say it was successful. You could have it say something only on error ✖, and then silence means success ✔.
That's how the Unix philosophy works:
The rule of silence, also referred to as the silence is golden rule, is an important part of the Unix philosophy that states that when a program has nothing surprising, interesting or useful to say, it should say nothing. It means that well-behaved programs should treat their users' attention and concentration as being valuable and thus perform their tasks as unobtrusively as possible. That is, silence in itself is a virtue. http://www.linfo.org/rule_of_silence.html
That's the way rm itself behaves.
If you are asking about the general case, as suggested by your question's title, you can run your script with sh -x scriptname to see what it's doing. It's also quite common to write diagnostic output into the script itself, and control it with an option.
#!/bin/sh
verbose=false
case $1 in -v | --verbose )
verbose=true
shift ;;
esac
say () {
$verbose || return
echo "$0: $#" >&2
}
say "Removing $dir ..."
rm -rf "$dir" || say "Failed."
If you run this script without any options, it will run silently, like a well-behaved Unix utility should. If you run it with the -v option, it will print some diagnostics to standard error.
rm -rf "My Folder" && echo "Done" || echo "Error!"
You can read more on creating a sequence of pipelines in bash manual
In the bash (and other similar shells) the ? environment variable gives you the exit code of the last executed command. So you can do:
#!/bin/sh
rm -rf "My Folder"
echo $?
UPDATE
If once the rm command has been executed the directory doesn't exist (because it has been successfully removed or because it didn't exist when the command was executed) the script will print 0. If the directory exists (which will mean that the command has been unable to remove it) then the script will print an exit code other than 0. If I understand properly the question this is exactly the requested behavior. If it is not, please correct me.
The previous answers was wrong : rm don't exit with error code > 0 when the dir isn't present.
Instead, I recommend to use :
dir='/path/to/dir'
if [[ -d $dir ]]; then
rm -rf "$dir"
fi
If you want rm to return a status, remove -f flag.
Example on Linux Mint (the dir doesn't exists):
$ rm -rf /tmp/sdfghjklm
$ echo $?
0
$ rm -r /tmp/sdfghjklm
$ echo $?
1