Update multiple heroku apps by batch script - windows

i have nearly 30~ heroku apps i want to update them by just 1 hit. i just made a simple batch but it doesn't focus to 2nd line after the first line is ok
cd C:\Users\Ofis\heroku\app1 && up.bat
cd C:\Users\Ofis\heroku\app2 && up.bat
cd C:\Users\Ofis\heroku\app3 && up.bat
cd C:\Users\Ofis\heroku\app4 && up.bat
cd C:\Users\Ofis\heroku\app5 && up.bat
cd C:\Users\Ofis\heroku\app6 && up.bat
up.bat =
git add .
git commit -m "update"
git push heroku master

You need to use call if you want to invoke a sub-script and return to the main script after it completes.
cd C:\Users\Ofis\heroku\app1 && call up.bat
cd C:\Users\Ofis\heroku\app2 && call up.bat

Related

Cannot create a bash alias or function for long command

I've been trying to create an alias of a long Git command. The command is of this format:
git clone "https://MyUserName#MyDomain.com/a/PathToRepo/RepoName" && (cd "RepoName" && mkdir -p .git/hooks && curl -Lo `git rev-parse --git-dir`/hooks/commit-msg https://MyUserName#MyDomain.com/tools/hooks/commit-msg; chmod +x `git rev-parse --git-dir`/hooks/commit-msg)
I am fine with either an alias or a bash function that can help me accomplish this.
Don't use aliases. They are in every aspect inferior to functions.
Writing this as a function also avoids the quoting errors you probably were bumping into when trying to create an alias (though it's not impossible to solve those, too; but if that's what you want, probably ask a new question with your actual attempt).
The following only has very small changes compared to your original (and to the extent that the original worked in the first place, it would have worked just as well without any changes at all).
func () {
git clone "https://MyUserName#MyDomain.com/a/PathToRepo/RepoName" &&
(
cd "RepoName" &&
mkdir -p .git/hooks &&
curl -Lo "$(git rev-parse --git-dir)/hooks/commit-msg" "https://MyUserName#MyDomain.com/tools/hooks/commit-msg" &&
chmod +x "$(git rev-parse --git-dir)/hooks/commit-msg"
)
}
The switch from legacy `command substitution` syntax to modern $(command substitution) syntax is mainly for aesthetic reasons. The addition of double quotes is crucial for handling file names with spaces or other shell metacharacters in them. Adding && instead of ; before chmod +x seemed to make sense for consistency.
Personally, I would calling git rev-parse --git-dir twice, and just create a variable with the name of the directory:
func () {
git clone "https://MyUserName#MyDomain.com/a/PathToRepo/RepoName" &&
local hookdir=RepoName/$(git -C "RepoName" rev-parse --git-dir)/hooks &&
mkdir -p "$hookdir" &&
curl -Lo "$hookdir/commit-msg" "https://MyUserName#MyDomain.com/tools/hooks/commit-msg" &&
chmod +x "$hookdir/commit-msg"
}
If you want to make the repository name and/or the URL configurable parameters, I would suggest to make the repo name the first parameter and the base URL the second, but this obviously depends on your use case.
func () {
git clone "${2-https://MyUserName#MyDomain.com/a/PathToRepo}/$1" &&
local hookdir="$1"/$(git -C "$1" rev-parse --git-dir)/hooks &&
mkdir -p "$hookdir" &&
curl -Lo "$hookdir/commit-msg" "https://MyUserName#MyDomain.com/tools/hooks/commit-msg" &&
chmod +x "$hookdir/commit-msg"
}
The syntax ${2-default} falls back to default if $2 is unset.

Bash run two commands both dependent on the first

I'm sure this has been asked but my search has been fruitless.
I want to run 3 bash commands in order with both the second and third only running if the first succeeded.
Example:
## Setup
mkdir so_test_tmp && cd so_test_tmp
echo "This is something" > something
cd ..
## Example commands
cd so_test_tmp ??? cat nothing ??? cd .. # 0.
cd so_test_tmp ??? cat something ??? cd .. # 1.
cd does_not_exist ??? cat nothing ??? cd .. # 2.
These three commands should always end in PWD. In 0. the first cd is run, then the last. In 1. all three commands successfully run. In 2. the first command fails so the second and third are not run.
What about?
pushd .; cmd1 && cmd2 && ... cmdn; popd
pushd . saves your current dir.
Then you execute your commands; you use && so that, if one fails, the others are not executed.
popd goes back to your initial dir.
EDIT: regarding your comment below, yes, this pushd .; popd construct is quite silly; it lets you forget about how the execution of each set of commands went.
pushd .; cd so_test_tmp && cat nothing; popd; # 0.
pushd .; cd so_test_tmp && cat something; popd; # 1.
pushd .; cd does_not_exist && cat nothing; popd; # 2.
You finish at your original dir after running the three sets of commands.
Within each set of commands, whenever a command fails, it shortcuts the execution of the others behind (see they are separated by &&).
If you need to know if each set of commands succeeded or not, you can always test the result of the execution (and go to your initial dir and save it again before running the following set of commands):
pushd .;
cd so_test_tmp && cat nothing && cd .. ; # 0.
test $? -eq 0 || (popd; pushd .) ;
cd so_test_tmp && cat something && cd ..; # 1.
test $? -eq 0 || (popd; pushd .) ;
cd does_not_exist && cat nothing && cd ..; # 2.
test $? -eq 0 || (popd; pushd .) ;
Specifically for cd somewhere && somecommand && cd ..
The cd .. is only necessary because you're doing cd so_test_tmp inside your parent shell, as opposed to the subshell that's fork()ed off to then be replaced with a copy of /bin/cat.
By creating an explicit subshell with ( ... ), you can scope the cd to its contents. By using exec for the last command in the subshell, you can consume it, balancing out the performance overhead of that subshell's creation.
(cd so_test_tmp && exec cat nothing) # 0.
(cd so_test_tmp && exec cat something) # 1.
(cd does_not_exist && exec cat nothing) # 2.
Note that this applies only when the command you're running in a subdirectory doesn't change the state of the shell that started it (like setting a variable). If you need to set a variable, you might instead want something like output=$(cd /to/directory && exec some_command).
Answering the more general question
Use && to connect the first command to a group with the second and third commands, and use ; to combine those 2nd and 3rd commands, if your goal is to ensure that both 2nd and 3rd run if-and-only-if the 1st succeeds.
cd so_test_tmp && { cat nothing; cd ..; } # 0.
cd so_test_tmp && { cat something; cd ..; } # 1.
cd does_not_exist && { cat nothing; cd ..; } # 2.
Setup:
$ cd /tmp
$ mkdir so_test_tmp
$ echo "This is something" > so_test_tmp/something
Wrapping an if/then/fi around OPs current examples:
$ if cd so_test_tmp; then cat nothing; cd ..; fi ; pwd
cat: nothing: No such file or directory
/tmp
$ if cd so_test_tmp; then cat something; cd ..; fi ; pwd
This is something
/tmp
$ if cd does_not_exist; then cat something; cd ..; fi ; pwd
-bash: cd: does_not_exist: No such file or directory
/tmp

Iterating over subdirectories: How do I recover if a command in one fails?

I have this for loop
for repository in ./*/; do
echo $repository && cd $repository && git checkout -b prod && cd - >/dev/null;
done
But if branch prod already exists it prints a message and exit the loop.
How can ignore this error and just go to the next directory ?
Thanks
So the problem is that git checkout -b prod returns failure to the shell if the branch already exists. Since it's connected to the next command (cd -) with the conditional operator &&, that next command only runs if git succeeds. So when git fails, the cd doesn't run, and your shell is left in the wrong directory to continue its loop.
In general, when you want your code to continue even if a command fails, separate the commands with ; or newlines instead of &&.
But a better solution in this case is to just do the cd in a subshell so that it doesn't affect the outer loop's working directory and you don't have to cd - at all:
for repository in ./*/; do
echo "$repository" && (
cd "$repository" && git checkout -b prod
)
done
That will work fine even if the branch creation fails. It will still print out the error message; if you don't want to see those, add the redirect:
for repository in ./*/; do
echo "$repository" && (
cd "$repository" && git checkout -b prod
) 2>/dev/null
done
I've also quoted the expansion of $repository in the commands, which you should almost always do in shell scripts. With the unquoted version, you would get an error if any of the repo directory names had spaces in them, for instance.
Also, that "no side effects in a subshell" thing is great for doing part of your work in a different directory, but it applies more widely. If you had a more complicated loop that set any shell variables or anything while it was in the subdir, those would also be lost. Just something to keep in mind.
Like this
home=$PWD
for repository in "$home"/*/; do
basename "$repository" # to 'echo' $repository
cd "$repository" && git checkout -b prod
done
Better use pushd and popd and additionally it is saver to use find:
while read -r repository; do
pushd "${repository}"
if git checkout -b prod; then
echo "git checkout success"
else
echo "git chechout error"
fi
popd
done < <( find . -mindepth 1 -maxdepth 1 -type d -print )

Sun Grid Engine - Submitting job from command line

I'd like to submit a job to the Sun Grid Engine using a single command line argument, rather than using a shell script. Can it be done?
Example:
I want to do this, and submit to the batch queue:
mkdir empty_directory && cd "empty_directory" && touch "empty_file.txt"
Rather than doing this:
dir_script.sh:
#!/bin/bash
mkdir empty_directory
cd empty_directory
touch empty_file.txt
Then:
qsub dir_script.sh
I do this all the time, using pipe (|):
echo "mkdir empty_directory && cd empty_directory && touch empty_file.txt" | qsub [options]

How to call a bat file in new window

I have a little bat file which calls other bat files:
cd C:\Users\Ofis\heroku\1134 && call up.bat
cd C:\Users\Ofis\heroku\5095 && call up.bat
cd C:\Users\Ofis\heroku\9469 && call up.bat
It works good, but I want it call .bat files in new windows so it will be synchronous and faster. How can I do this?
You can make use of start :D
cd C:\Users\Ofis\heroku\1134 && start up.bat
cd C:\Users\Ofis\heroku\5095 && start up.bat
cd C:\Users\Ofis\heroku\9469 && start up.bat

Resources