Passing the parameters based on the filename in shell script - shell

I have a requirement where I need to look for the new files in a particular location. Once I see a new file, I need to run other script which will move that file to a
different location. Now I want the first script to look for new files. Once I find any files, based on the filename, I need to trigger the second script by passing the corresponding keyword as parameters.
Suppose the filename is abc_20.txt. In my first script it has to look for abc*.text. Once I find such a file, I need to trigger the second script by passing the parameter as abc.
Second script command: sh 2nd_script.sh abc
Could you please help me how to compare the filename (abc_20.txt) with predefined keyword (abc*.text) and how to pass the corresponding keyword to the second script (abc)?

how to compare the filename (abc_20.txt) with predefined keyword (abc*.text)
The term "keyword' is strangely used here - a string abc*.text is no keyword in shell, it has no special meaning.
The simplest and most portable way is to use case:
case "abc_20.txt" in
abc*.text) echo YES; ;;
*) echo NO; ;;
esac
how to pass the corresponding keyword to the second script(abc)
As with any information passed to any script, the simplest would be to use positional parameters.
corresponding_keyword=something
second_script "$corresponding_keyword"

If there may be 2nd_script.sh in the current directory,
you can execute 2nd_script.sh with the file matches "abc*.text" .
find . -name "abc*.text" -exec sh 2nd_script.sh '{}' \;

Related

Replace literal at HTML using Unix shell script

I have a series of scripts declared in an HTML with the following format:
xxx.jfhdskfjhdskjfhdskjfjioe3874.bundle.js
The part between the periods is a dynamic hash, but it will always be an alphanumeric with the same positions. My problem is that I need to dynamically modify that hash, with the new generated files, which are in the same directory as the HTML itself. Is there a clean way to do it in Unix with a script?
You must be more specific: You want to generate new hashes for all scripts in this directory or need just a tool to change one by one basis? where do you get new hashes from? Below I attached simple script to change the part between first and second period sign. Script should be called with old name as first argument and new hash as second argument. It could be compressed to just one line but I used variables for clarity.
#! /bin/sh
OLDNAME=$1
NEWHASH=$2
NEWNAME=$(printf "%s" "$OLDNAME" | sed "s/^\([^\.]*\)\.[^\.]*\.\(.*\)/\1\.$NEWHASH\.\2/")
echo $NEWNAME

Create shell alias with value from current path

I want to create a shell alias which would run
command ew --constantswitch --anotherconstantswitch <name>
Now the value name needs to be extracted from the current path. the current path looks like this
[username#path-to-shell-xxxxxxxx]/path/to/directory/with/name%
How can I create an alias such that when I run aliasX it will
Extract the name from current path (which is last value of the prompt)
Add this path to the command above and execute.
An alias may not be competent for the job, but a function surely do. Try this code:
myfunc() {
command ew --constantswitch --anotherconstantswitch "${PWD##*/}"
}
The trick is ${PWD##*/}. You know the automatic variable $PWD is exactly what you get when you run pwd, as well as Bash's builtin string substitution ${var##pattern} that removes pattern from the left of the variable with maximum match. So ${PWD##*/} removes everything except the name after the last slash, which as you described is what you're looking for.
In practice, a function is more versatile than an alias. If you still need to add extra arguments to the command, append "$#" to the end of the command inside the function, so any argument that you pass to the function will be forwarded to the command.
Since you're not trying to do anything involving arguments, an alias is actually possible:
alias aliasX='echo "${PWD##*/}"'
This will print the current directory name when you use aliasX. Or, using your example:
alias aliasX='command ew --constantswitch --anotherconstantswitch "${PWD##*/}"'
Notice that the alias must be in single quotes or $PWD will expand when you define it instead of when you use it.
For anything slightly more complex, you should use a function instead of an alias, as shown in iBug's answer.

Issue saving result of "find" function in a shell script

I'm pretty new to shell scripting, but it's been great in helping me automating cumbersome tasks in OS X.
One of the functions I'm trying to write in a new script needs to find the specific filename in a subdirectory given a regex string. While I do know that the file exists, the version (and therefore filename itself) is being continually updated.
My function is currently as follows:
fname(){
$2=$(find ./Folder1 -name "$1*NEW*")
}
Which I'm then calling later in my script with the following line:
fname Type1 filename1
What I'm hoping to do is save the filename I'm looking for in variable filename1. My find syntax seems to be correct if I run it in Terminal, but I get the following error when I run my script:
./myscript.sh: line 13: filename1=./Folder1/Type1-list-NEW.bin: No such file or directory
I'm not sure why the result of find is not just saving to the variable I've selected. I'd appreciate any help (regardless of trivial this question may end up being). Thanks!
EDIT: I have a bunch of files in the subdirectory, but with the way I'm setting that folder up I know my "find" query will return exactly 1 filename. I just need the specific filename to do various tasks (updating, version checking, etc.)
The syntax for writing output to a file is command > filename. So it should be:
fname() {
find ./Folder1 -name "$1*NEW*" > "$2"
}
= is for assigning to a variable, not saving output in a file.
Are you sure you need to put the output in a file? Why not put it in a variable:
fname() {
find ./Folder1 -name "$1*NEW*"
}
var=$(fname Type1)
If you really want the function to take the variable name as a parameter, you have to use eval
fname() {
eval "$2='$(find ./Folder1 -name "$1*NEW*")'"
}
Okay, so I'm reading this as, you want to take the output of the find and save it in a shell variable given by $2.
You can't actually use a shell variable to dynamically declare the name of a new shell variable to rename, when the shell sees an expansion at the beginning of a line it immediately begins processing the words as arguments and not as an assignment.
There might be some way of pulling this off with declare and export but generally speaking you don't want to use a shell variable to hold n file names, particularly if you're on OS X, those file names probably have whitespaces and you're not protecting for that in the way your find is outputting.
Generally what you do in this case is you take the list of files find is spitting out and you act on them immediately, either with find -exec or as a part of a find . -print0 | xargs -0 pipeline.

how to filter a command subsitution from the resulting value of a readlink for symlink?

This may be poorly titled as I'm not fully sure what the process is called.
Basically I want to get only the last part of a symlink path, and I'm trying to use the same method I use with PWD.
For example:
if I do
PWD
it prints
/opt/ct/mydir
if I do
echo ${PWD##*/}
it prints only the last part
mydir
So using that design I can do
readlink mysymlink
which gives
/opt/ct/somedir
and I can do
TMP=$(readlink mysymlink)
echo ${TMP##*/}
and it will print
somedir
So now how can I combine that last part into one line like
TMP=$(readlink mysymlink && echo ${TMP##*/})
???
The example I show gives me 2 concatenated results.. one with the full path and one with just the part I want. I only want that last directory.
I also tried
TMP=${ $(readlink mysymlink)##*/}
to no avail
Variable substitution suffixes can only be used with variables, not command substitutions. You either have to set the variable and modify it in separate statements, as in your first attempt, or use additional command substitutions:
TMP=$(basename $(readlink))

Simple map for pipeline in shell script

I'm dealing with a pipeline of predominantly shell and Perl files, all of which pass parameters (paths) to the next. I decided it would be better to use a single file to store all the paths and just call that for every file. The issue is I am using awk to grab the files at the beginning of each file, and it's turning out to be a lot of repetition.
My question is: I do not know if there is a way to store key-value pairs in a file so shell can natively do something with the key and return the value? It needs to access an external file, because the pipeline uses many scripts and a map in a specific file would result in parameters being passed everywhere. Is there some little quirk I do not know of that performs a map function on an external file?
You can make a file of env var assignments and source that file as need, ie.
$ cat myEnvFile
path1=/x/y/z
path2=/w/xy
path3=/r/s/t
otherOpt1="-x"
Inside your script you can source with either . myEnvFile or the more versbose version of the same feature sourc myEnvFile (assuming bash shell) , i.e.
$cat myScript
#!/bin/bash
. /path/to/myEnvFile
# main logic below
....
# references to defined var
if [[ -d $path2 ]] ; then
cd $path2
else
echo "no pa4h2=$path2 found, can't continue" 1>&1
exit 1
fi
Based on how you've described your problem this should work well, and provide a-one-stop-shop for all of your variable settings.
IHTH
In bash, there's mapfile, but that reads the lines of a file into a numerically-indexed array. To read a whitespace-separated file into an associative array, I would
declare -A map
while read key value; do
map[$key]=$value
done < filename
However this sounds like an XY problem. Can you give us an example (in code) of what you're actually doing? When I see long piplines of grep|awk|sed, there's usually a way to simplify. For example, is passing data by parameters better than passing via stdout|stdin?
In other words, I'm questioning your statement "I decided it would be better..."

Resources