Run Code Only If Script Called from the Command Line

Run code only if script called from the command line

It is common to put this at the bottom of your script:

if __FILE__==$0
# this will only run if the script was the main, not load'd or require'd
end

Because I like to see the main action at the top of my file, I usually put a def run! as the first method in the file and then end the file with:

run! if __FILE__==$0

How can I run a function from a script in command line?

If the script only defines the functions and does nothing else, you can first execute the script within the context of the current shell using the source or . command and then simply call the function. See help source for more information.

Run only parts of shell script with arguments

You can abstract the segments of your code into functions, then trigger which functions should be run with command line arguments. In the example below, you can run the script with, e.g. ./script.sh --install-requirements --aws-copy, or equivalently ./script.sh -i -a.

If you prefer, case statements (similar to switch in C/C++) can be used instead of the multiple ifs below, see resources at the bottom for more details.

If you would like to use command line arguments inside of the functions, you can forward them with $@, like this: InstallRequirements "$@". You can also pass any other arguments, like this: InstallRequirements arg1 arg2, the function will see them the same way a script sees command line arguments.

Also note it's almost always better to enclose variables in double quotes: rm -rf "$filename" instead of rm -rf $filename. The rm without the quotes is very dangerous if the filename contains spaces.

#!/bin/bash

function InstallRequirements {
pip install -r ./docker/requirements.txt
}

function ZipFile {
ZIP_FILE=spark.zip
zip -r "$ZIP_FILE" file.py
}

function AwsCopy {
S3_BUCKET_PATH=$S3_BUCKET_PATH
aws s3 cp "$ZIP_FILE" "$S3_BUCKET_PATH/lib/"
}

###

for arg in "$@"; do
if [[ "$arg" = -i ]] || [[ "$arg" = --install-requirements ]]; then
ARG_INSTALL_REQUIREMENTS=true
fi
if [[ "$arg" = -z ]] || [[ "$arg" = --zip-file ]]; then
ARG_ZIP_FILE=true
fi
if [[ "$arg" = -a ]] || [[ "$arg" = --aws-copy ]]; then
ARG_AWS_COPY=true
fi
done

###

if [[ "$ARG_INSTALL_REQUIREMENTS" = true ]]; then
InstallRequirements
fi

if [[ "$ARG_ZIP_FILE" = true ]]; then
ZipFile
fi

if [[ "$ARG_AWS_COPY" = true ]]; then
AwsCopy
fi

Resources:

  • Linuxize: Bash Functions
  • Unix & Linux Stack Exchange: Pass arguments to function exactly as-is
  • Bash Guide for Beginners: 7.3. Using case statements
  • Nick Janetakis: Here's Why You Should Quote Your Variables in Bash

Rscript detect if R script is being called/sourced from another script

EDIT

Okay, this is a LOT more like python's __name__ trick. (Previous answer below, kept for historical reasons.)

function1 <- function(etc,etc) {}
function2 <- function(etc,etc) {}

if (sys.nframe() == 0L) {
library(optparse)
# ...
}

It is about as minimalist as one could hope for, does not require the sourceing script to know anything about it, and seems to work well even when nested.

Other possible mechanisms could be used (additional functions required) by looking at script names, per Rscript: Determine path of the executing script. Many plausible (some really good) solutions exist there, but they all require a pre-defined function not defined in a base package (or non-trivial code included in the script to be sourced). If you want to "assume package X is installed", then your script becomes potentially non-portable.


(Previous answer, I suggest you use above.)

I'll throw this out as a hack ... it's only slightly less janky than your workaround, but it relies on the calling script knowing something of what the called script is testing for.

If the calling script sets a variable:

BEING_SOURCED_FROM_SOMEWHERE <- TRUE

then the called script can check for it:

function1 <- function(etc,etc) {}
function2 <- function(etc,etc) {}

if (! exists("BEING_SOURCED_FROM_SOMEWHERE")) {
library(optparse)
# ...
}

I don't like it. It isn't as flexible as python's

if __name__ == "__main__":
import optparse
# ...

But I think I dislike it less than your use of save and load for function definitions.

run script from CLI but prevent running when included

You can test if $argv[0] == __FILE__ to see if the file called form the command line is the same as the included file.

class foo {
public function __construct() {

// Output Hello World if this file was called directly from the command line
// Edit: Probably need to use realpath() here as well..
if (isset($argv) && realpath($argv[0]) == __FILE__) {
echo("Hello world");
}
}
}

How to get a batch file only processed if it's called from another batch file?

I cannot think of any way that would prevent the bare "run" of the called script. Possibly that might only be done using NTFS permissions.

What you can do quickly is something like this:

MOTHERBATCH.bat

call compileData.bat SomePASSPHRASE

compileData.bat

@echo off
if not "%1"=="SomePASSPHRASE" (
echo "You can not run this script directly, please run MOTHERSCRIPT.bat."
exit /B 1
)

echo "Passphrase is correct, code is executed..."

Detecting if script executed from command line in Racket?

Racket has the concept of main submodules. You can read about them in the Racket Guide section entitled Main and Test Submodules. They do precisely what you want—when a file is run directly using racket or DrRacket, the main submodule is executed. If a file is used by another file using require, the main submodule is not run.

The Racket equivalent of your Python program would be the following:

#lang racket

(define (foo)
"foo!")

(module+ main
(foo))

Run function from the command line

With the -c (command) argument (assuming your file is named foo.py):

$ python -c 'import foo; print foo.hello()'

Alternatively, if you don't care about namespace pollution:

$ python -c 'from foo import *; print hello()'

And the middle ground:

$ python -c 'from foo import hello; print hello()'

Run function in script from command line (Node JS)

No comment on why you want to do this, or what might be a more standard practice: here is a solution to your question.... Keep in mind that the type of quotes required by your command line may vary.

In your db.js, export the init function. There are many ways, but for example:

    module.exports.init = function () {
console.log('hi');
};

Then call it like this, assuming your db.js is in the same directory as your command prompt:

node -e 'require("./db").init()'

If your db.js were a module db.mjs, use a dynamic import to load the module:

node -e 'import("./db.mjs").then( loadedModule => loadedModule.init() )'

To other readers, the OP's init function could have been called anything, it is not important, it is just the specific name used in the question.



Related Topics



Leave a reply



Submit