How to pass an asterisk(*) to a command inside a Bash script? - bash

I have done quite a bit of looking on Google, stackexchange, stackoverflow, etc. So far none of the examples satisfies a quite simple use case for using an asterisk character (not as a wildcard) within a bash script.
The following command examples work exactly as needed in the (interactive) terminal window. Both commands give the same results.
find /home/will/ref/ -path "*Java Develop*.pdf"
#
target="Java Develop"
find /home/will/ref/ -path "*$target*.pdf"
The question, and objective, is how to successfully put that command into a script with the find target
"Java Develop"
Passed as an argument? For a script named, get-ref as follows.
get-ref "Java Develop"`
None of the following (not the exhaustive) list of attempts:
find /home/will/ref/ -path \"\*$target\*.pdf\"
find /home/will/ref/ -path \"*$target*.pdf\"
find /home/will/ref/ -path "*$target*.pdf"
Plus several variations around those examples including putting the -path argument string in a variable -- All so far manage to split the target using the space or accept the argument and return nothing. When used on the command-line, about 3 x files are returned.
To be clear though, I'm not concerned with the space inside $target because that side seems to work OK. Ultimately the $target will be a script parameter anyway.
-- update 2015-12-22 --
It appears that the Bash version is important. This version is:
$ bash -version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
A friend ran more or less the same options as above and they work. When I ran his script on my PC, same result, no output.
To answer the questions:
Everything fails the either by not 'finding' something; or by giving an error about the string "Devel" because of mis-balance quotes we presume.
I used set -x and the results have found an answer that work on this bash (see posted answer).
I'll just post my version as an answer; perhaps someone will have a better method or at least an explanation that lets Bash off the hook.
The concern is that the asterisks(*) are somehow Not being seen or processed as expected when the same command is used inside a Bash script.

With a little help, we have found a working version for this script. It is quite short so I'll post it here and give an example.
First the script, get-ref:
#!/bin/bash
#
# file: get-ref
# usage: get-ref <pattern>
#
# <pattern> ...... target pattern to find
# _____________________________________
#
target=$1
searchPath="$HOME/ref/"
#
# _____________________________________
#
#
find $searchPath -path "*$target*.pdf"
#
echo " -------------------------------"
echo
exit
(Debugging code omitted). This script looks like pattern #3 from the question. Which may mean that I had the answer once but it didn't work for some other reason (I hate it when that happens).
This method worked with my friend's Bhodi Linux distro although <shrug> his set -x didn't show the single-quoting(') below. However ...
The way -path is handled was revealed when we used, set -x which showed the find command looks like this to Bash:
+ find /home/william/_ref/ -path '"*Java Dev*.pdf"'
It seems the script (and not, the command terminal) injects single-quotes(') around the -path argument. This was the missing factor.
praise the set -x built-in
Output example:
$ get-ref "Java Dev"
+ find /home/william/_ref/ -path '*Java Dev*.pdf'
/home/will/ref/technique/games/The Well-Grounded Java Developer.pdf
/home/will/ref/technique/bi/JasperReports 3.5 for Java Developers.pdf
/home/will/ref/lang/ada/Ada for the Cpp or Java Developer.pdf
Finale ...
I'm happy that I can (now) find the document or eBook I want when I need to. Thank you for the comments they were definitely on-track.

Related

copy paste code works but not as a script

I wrote a script with six if statements that looks like this:
#!/usr/bin/bash
if [ -n $var1 ]
then
for f in /path/*.fastq.gz
do
x=${f/%.fastq.gz/_sample1-forward.fastq.gz}
y=${f/%.fastq.gz/_sample1-forward.out}
q=${f/%.fastq.gz/_temp.fastq.gz}
command [options] -i $f -o $temp${x##*/}
cp $temp${x##*/} $temp${q##*/}
done
else
echo "no $var1"
for f in /path/*.fastq.gz
do
q=${f/%.fastq.gz/_temp.fastq.gz}
cp $f $temp${q##*/}
done
fi
The other five statements do a similar task for var2 to var6. When I run the script I get unexpected output (no errors no warnings), but when I copy paste each of the if statements to terminal I end up with the exact result I would expect. I've looked for hidden characters or syntax issues for hours now. Could this be a shell issue? Script written on OSX (default zsh) and execution on server (default bash). I have a feeling this issue is similar but I couldn't find an answer to my issue in the replies.
Any and all ideas are most welcome!
Niwatori
You should maybe look at the shebang. I think proper usage would be #!/usr/bin/env bash or #!/bin/bash.
thanks for the help, much appreciated. Shebang didn't seem to be the problem although thanks for pointing that out. Shellcheck.net reminded me to use
[[ ]]
for unquoted variables, but that didn't solve the problem either. Here's what went wrong and how I 'fixed' it:
for every variable the same command (tool) is used which relies on a support file (similar in format but different content). Originally, before every if statement I replaced the support file for the previous variable with the one needed for the current variable. For some reason (curious why, any thoughts are welcome) this didn't always happen correctly.
As a quick workaround I made six versions of the tool, all with a different support file and used PYTHONPATH=/path/to/version/:$PYTHONPATH before every if statement. Best practice would be to adapt the tool so it can use different support files or an option that deals with repetitive tasks but I don't have the time at the moment.
Have a nice day,
Niwatori

How to extract only version from "go version" command using sed or other bash command in bash shell script running on Debian 10

The command go version currently prints go version go1.13.6 linux/amd64. I installed from the go website rather than Debian packages as the version is old. Therefore traditional ways to extract the version number like dpkg -s cannot be used.
I've explored sed commands to extract only the number (1.13.6) like this other question on this site which is similar I grant you, however after reading various sources online about whats possible with sed and my limited knowledge I've been unable to work out how to tell sed to find the starting point, yet alone make it future proof for new versions which may be slight alterations of this number format. I've tried to explore ways to say "find the 3rd to last number" so that I can then work backwards. Or, "find the 2nd word 'go'".
Current efforts have been purely theoretical, as I can't find where to begin, I've not included any attempts.
Can it be done?
$ v=`go version | { read _ _ v _; echo ${v#go}; }`
$ echo $v
1.13.6
Further reading:
Compound commands.
The read comand.
Parameter expansion.
Command substitution.

Translating OS X Bash Script for Windows

I use Hedge to transfer Magic Lantern video files shot on my Canon 5D Mark III.
On OS X, I'm able to use Automator to set up a bash script, to execute an mlv_dump to transfer the files from MLV into cDNG sequences.
The script I use currently is:
cd "$(dirname "$1")"
for f in "$#"; do
if [[ -f $f ]]; then
filename=${f##*/};
folder=${filename%.*}
mkdir "${folder}";
~/mlv_dump --dng $f -o ${folder}/${folder}_;
fi
done
Can this easily translate into a Windows equivalent?
Thanks,Thomas
As with any translation between programming languages, there's (a) an as-literal-as-possible approach, which contrasts with (b), an not-immediately-obvious-but-in-the-spirit-of-the-target-language approach.
(b) is always preferable in the long run.
Use PowerShell, because it is the - far superior - successor to the "Command Prompt" (cmd.exe) and its batch files.
The code below is an attempt at (b), in PowerShell (v3+ syntax).
I encourage you to study the code and post an explanation of it in an answer of your own, so that others may benefit too.
To help with the analysis, consider the following resources:
The official Windows PowerShell get-started page and the equivalent for PowerShell Core.
This series of articles is a great, recipe-oriented introduction to PowerShell.
http://hyperpolyglot.org/shell juxtaposes the syntax of POSIX-like shells such as bash with that of cmd.exe and PowerShell in concise, tabular form.
PowerShell-idiomatic translation of your code:
param(
[Parameter(Mandatory, ValueFromRemainingArguments)]
[System.IO.FileInfo[]] $LiteralPath
)
$outputBaseFolder = Split-Path -Parent $LiteralPath[0].FullName
foreach ($f in $LiteralPath) {
if ($f.exists) {
$outputFolder = Join-Path $outputBaseFolder $f.BaseName
New-Item -ItemType Directory $outputFolder
& "$HOME/mlv_dump" --dng $f.FullName -o "$outputFolder/$($f.BaseName)_"
} else {
Write-Warning "Item doesn't exist or is not a file: $($f.FullName)"
}
}
Easy, is a relative answer specific to the skills of the individual, As the others have commented, there is no out of the box thing / tool you can use or buy to do this. It's all manual work, using the pointers and others who have tried to see what you can glean to accomplish you use case.
For example, this, in your block...
filename=${f##*/};
folder=${filename%.*}
mkdir "${folder}";
... is easily translated into...
$filename='PathToFileName'
$foldername='PathToFolder'
mkdir 'FolderName'
Now, that translation is really simplistic, and obviously not complete. That is something you'll have to figure out, using the resources pointed to and the PowerShell built-in help file and those examples.
There are several posts on this very forum on this conversion topic and how others have come to a consensus oh what / if anything can be done.
For example the below will highlight the efforts you'll need to traverse to accomplish X or Y.
Convert simple Bash script to PowerShell?
I am looking to port this bash code to PowerShell. Can anyone shed
some PowerShell light on this one?
Convert simple Bash script to PowerShell?
Convert bash script into Windows script
I have the following Unix shell script. I would like to convert this
into a Windows .bat file (I know I can use Cygwin instead of adapting
it to a Windows environment. But Cygwin is not an option for me).
Convert bash script into Windows script
Convert xargs Bash command to PowerShell?
I've got a simple Bash command to resize some images automatically on
a low-traffic website using ImageMagick - I'd like to convert this to
a PowerShell command so I don't have to install Cygwin on my
webserver.
Convert xargs Bash command to PowerShell?
As noted, there are paid for avenues / even online ones who can potentially be an avenue.
But, you should really read up a bit more on how to do specific things, like..
Creating files and folders
Accessing/Reading files, importing files, filtering files
Loops
Operators (comparison and assignment)
Navigating the file system/PSDrive

Get results of command from Cygwin in Batch

The Problem
I'm a little new to Cygwin and I'm trying to run a shell script in Cygwin from Batch and get the return value. I've been searching around, and I tried using C:\cygwin[64]\bin\bash[64].exe and even messing with C:\cygwin[64]\Cygwin.bat but to no avail.
Basically, I just want to be able to, from batch, interact with bash (from Cygwin). Please excuse me if this seems trivial to you, as I am rather new to Cygwin. Anyways, I have yet to find a working online solution.
Example Sudo Code:
cygwin-magic "echo shell-command"
#=> shell-command
Some Stuff I've Tried
I found all of these things from a lengthy Google hunt. Nothing did what I wanted it to.
"C:\cygwin[64]\bin\base[64].exe" /cygdrive/c/users/<me>/desktop/tmp.sh
#=> ZWNobyAiaGVsbG8i
"C:\cygwin[64]\bin\base[64].exe" -d /cygdrive/c/users/<me>/desktop/tmp.sh
#=> y▒h/usr/bin/base[64]: invalid input
"C:\cygwin[64]\bin\base[64].exe" -d -i /cygdrive/c/users/<me>/desktop/tmp.sh
#=> y▒h▒▒e/usr/bin/base[64]: invalid input
"C:\cygwin[64]\bin\base[64].exe" -d -i "echo hello"
#=> /usr/bin/base[64]: echo hello: No such file or directory
# I kind of gave up on all of my other attempts and tried this because why not? Surprise surprise, it didn't work (not that I expected it to).
"C:\cygwin[64]\Cygwin.bat"
echo "hello"
Contents of tmp.sh
Simply,
echo "hello"
Purpose
The reason I want to do this from batch is that I want to interact with bash from another language through batch (on Windows). I've got my solution planned out in that third language, but it's just the batch-to-cygwin that's not working.
Notes
Windows 7 Home Premium x64
Cygwin x64
I wrote all 64s in the code as [64] because I know 32-bit builds don't use that.
If I missed something or my question's a little off (too broad, too specific, etc.), please comment and I'll change it.
Perhaps you meant "C:\cygwin[64]\bin\basH[64].exe" not "C:\cygwin[64]\bin\base[64].exe"

How do I use SSFT (Shell Scripts Frontend Tool) on Ubuntu (or any Linux)?

I can't find a man page or any help for ssft. I want to use it in my bash scripts to select either kdialog (if on KDE) or zenity (if on gnome).
See Shell Scripts Frontend Tool
Surely the help pages are somewhere, but I must be overlooking them.
I am running Debian 6.0 Squeeze stable right now, and it has a manpage for ssft.sh. Try man ssft.sh. If that doesn't do what you want, let me know and you and I will figure out what does.
Update: All right. You have tried the manpage, which doesn't tell you what you want to know. There does not appear to exist any more thorough documentation for Ssft (maybe, when this is all over, you will write and contribute that very documentation). However, in Ssft's source appears to be a test script that makes the software do the various things it is designed to do. Sometimes, a good example is even better than a manual. That test script may be just what you need.
To extract the test script, issue a sequence of commands like the following sequence.
$ cd /tmp
$ apt-get source ssft
$ ls
$ cd ssft-0.9.13 # (Your version number may differ from 0.9.13.)
$ ls
$ cd tests
$ ls
When I do the above, the last ls listing reveals a shell script named ssft-test.sh. Inside that script appear to be several examples of how to use ssft.sh correctly.
http://man.devl.cz/man/1/ssft.sh
ssft.sh(1)
SSFT
Name
ssft.sh - library of shell script frontend functions
Synopsis
. ssft.sh
Description
ssft.sh is a library of shell functions that must be sourced from other scripts. If the script is executed without arguments it prints an usage message and also supports the options --doc, --help and --version.
To get a list of available functions call the script with the --doc argument and to get a description of what a given function does call the script with --doc FUNCTION_NAME.
On the typical case the library must be sourced and the SSFT_FRONTEND variable must be set to the desired frontend (zenity, dialog or text); if the variable is not set the default frontend is noninteractive.
To choose the theorically best looking frontend use the function ssft_choose_frontend as follows:
. ssft.sh [ -n "$SSFT_FRONTEND" ] || SSFT_FRONTEND="$( ssft_choose_frontend )"
Written by Sergio Talens-Oliag .
$ /usr/bin/ssft.sh
Shell Script Frontend Tool (version 0.9.13)
Usage: . ssft.sh
When called directly the program supports the following options:
-d,--doc [FUNCTIONS] Prints the list of available functions. If function names are given prints functions' documentation.
-h,--help This message
-v,--version File version
functions:
$ /usr/bin/ssft.sh -d
ssft_set_textdomain
ssft_reset_textdomain
ssft_choose_frontend
ssft_print_text_title
ssft_display_message
ssft_display_error
ssft_display_emsg
ssft_file_selection
ssft_directory_selection
ssft_progress_bar
ssft_read_string
ssft_read_password
ssft_select_multiple
ssft_select_single
ssft_yesno
ssft_show_file

Resources