cp command won't run if executed from shell script - linux

i have very simple shell script
#!/bin/bash
cp -rf /var/www/ksite/app2/* /var/www/ksite/app
echo "----"
echo "done"
but seems cp command fails
if i execute
cp -rf /var/www/ksite/app2/* /var/www/ksite/app
from terminal everything work ok. Can someone tell me how to include cp in shell script?
Thanks

We seem to have doubt as to how this script fails. If there is no error message then this is a strange one. I suggest:
On the command line (which works), do a which cp
Whatever the reply, then copy that and use it as the cp in the script (e.g. /bin/cp)
Check the widcard expansion, run your script with bash -x script-name and see if you get what you expect.
echo $? after the copy in the script - if it is zero then it (thinks it) worked.
Do a ls -ld /var/www/ksite/app from your script, maybe someone set a symbolic link?
If it still fails, source the script from the command-line and see if that works . script-name
Double check that the copy did actually fail! (maybe that should be step 1.)

Make sure you really have bash at /bin/bash. I think a batter hash bang is:
#!/usr/bin/env bash
This uses the env command to locate the bash binary and set the environment.

I had similar problem. What helped me:
I used windows and putty to write script, so I had \r\n at the end of lines. Be sure, you have only \n symbol.
I copied files and the only way it worked for me at script was cp <source_dir>/fileName <dest_dir>/fileName whereas at command line cp <source_dir>/fileName <dest_dir> worked well too.

Just covering all the bases .. do the permissions vary between the excutions .. i.e. do you execute one with sudo/root privileges, the other as user (unlikely, but thought I'd ask since we don't know what the exact error is)

Similar issue to Vladmir where the script was created in Windows. I created a new file "my_bash_script.sh" in the linux environment using VIM, then read the contents of my script into the file:
:r file_made_in_windows.sh
Then I saved, closed, then set the file as executable:
chmod 744 my_bash_script.sh
From there, I ran the script:
./my_bash_script.sh
...and it worked. What a weird issue. I was confounded for a moment.

Related

Running `cd` in `.sh` file in anaconda environment on Linux [duplicate]

I'm trying to write a small script to change the current directory to my project directory:
#!/bin/bash
cd /home/tree/projects/java
I saved this file as proj, added execute permission with chmod, and copied it to /usr/bin. When I call it by:
proj, it does nothing. What am I doing wrong?
Shell scripts are run inside a subshell, and each subshell has its own concept of what the current directory is. The cd succeeds, but as soon as the subshell exits, you're back in the interactive shell and nothing ever changed there.
One way to get around this is to use an alias instead:
alias proj="cd /home/tree/projects/java"
You're doing nothing wrong! You've changed the directory, but only within the subshell that runs the script.
You can run the script in your current process with the "dot" command:
. proj
But I'd prefer Greg's suggestion to use an alias in this simple case.
The cd in your script technically worked as it changed the directory of the shell that ran the script, but that was a separate process forked from your interactive shell.
A Posix-compatible way to solve this problem is to define a shell procedure rather than a shell-invoked command script.
jhome () {
cd /home/tree/projects/java
}
You can just type this in or put it in one of the various shell startup files.
The cd is done within the script's shell. When the script ends, that shell exits, and then you are left in the directory you were. "Source" the script, don't run it. Instead of:
./myscript.sh
do
. ./myscript.sh
(Notice the dot and space before the script name.)
To make a bash script that will cd to a select directory :
Create the script file
#!/bin/sh
# file : /scripts/cdjava
#
cd /home/askgelal/projects/java
Then create an alias in your startup file.
#!/bin/sh
# file /scripts/mastercode.sh
#
alias cdjava='. /scripts/cdjava'
I created a startup file where I dump all my aliases and custom functions.
Then I source this file into my .bashrc to have it set on each boot.
For example, create a master aliases/functions file: /scripts/mastercode.sh
(Put the alias in this file.)
Then at the end of your .bashrc file:
source /scripts/mastercode.sh
Now its easy to cd to your java directory, just type cdjava and you are there.
You can use . to execute a script in the current shell environment:
. script_name
or alternatively, its more readable but shell specific alias source:
source script_name
This avoids the subshell, and allows any variables or builtins (including cd) to affect the current shell instead.
Jeremy Ruten's idea of using a symlink triggered a thought that hasn't crossed any other answer. Use:
CDPATH=:$HOME/projects
The leading colon is important; it means that if there is a directory 'dir' in the current directory, then 'cd dir' will change to that, rather than hopping off somewhere else. With the value set as shown, you can do:
cd java
and, if there is no sub-directory called java in the current directory, then it will take you directly to $HOME/projects/java - no aliases, no scripts, no dubious execs or dot commands.
My $HOME is /Users/jleffler; my $CDPATH is:
:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work
Use exec bash at the end
A bash script operates on its current environment or on that of its
children, but never on its parent environment.
However, this question often gets asked because one wants to be left at a (new) bash prompt in a certain directory after execution of a bash script from within another directory.
If this is the case, simply execute a child bash instance at the end of the script:
#!/usr/bin/env bash
cd /home/tree/projects/java
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
exec bash
To return to the previous, parental bash instance, use Ctrl+D.
Update
At least with newer versions of bash, the exec on the last line is no longer required. Furthermore, the script could be made to work with whatever preferred shell by using the $SHELL environment variable. This then gives:
#!/usr/bin/env bash
cd desired/directory
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
$SHELL
I got my code to work by using. <your file name>
./<your file name> dose not work because it doesn't change your directory in the terminal it just changes the directory specific to that script.
Here is my program
#!/bin/bash
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace
Here is my terminal
nova:~ Kael$
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$
simply run:
cd /home/xxx/yyy && command_you_want
When you fire a shell script, it runs a new instance of that shell (/bin/bash). Thus, your script just fires up a shell, changes the directory and exits. Put another way, cd (and other such commands) within a shell script do not affect nor have access to the shell from which they were launched.
You can do following:
#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash
EDIT: This could be 'dotted' as well, to prevent creation of subsequent shells.
Example:
. ./previous_script (with or without the first line)
On my particular case i needed too many times to change for the same directory.
So on my .bashrc (I use ubuntu) i've added the
1 -
$ nano ~./bashrc
function switchp
{
cd /home/tree/projects/$1
}
2-
$ source ~/.bashrc
3 -
$ switchp java
Directly it will do: cd /home/tree/projects/java
Hope that helps!
It only changes the directory for the script itself, while your current directory stays the same.
You might want to use a symbolic link instead. It allows you to make a "shortcut" to a file or directory, so you'd only have to type something like cd my-project.
You can combine Adam & Greg's alias and dot approaches to make something that can be more dynamic—
alias project=". project"
Now running the project alias will execute the project script in the current shell as opposed to the subshell.
You can combine an alias and a script,
alias proj="cd \`/usr/bin/proj !*\`"
provided that the script echos the destination path. Note that those are backticks surrounding the script name.
For example, your script could be
#!/bin/bash
echo /home/askgelal/projects/java/$1
The advantage with this technique is that the script could take any number of command line parameters and emit different destinations calculated by possibly complex logic.
to navigate directories quicky, there's $CDPATH, cdargs, and ways to generate aliases automatically
http://jackndempsey.blogspot.com/2008/07/cdargs.html
http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5827311.html
In your ~/.bash_profile file. add the next function
move_me() {
cd ~/path/to/dest
}
Restart terminal and you can type
move_me
and you will be moved to the destination folder.
You can use the operator && :
cd myDirectory && ls
While sourcing the script you want to run is one solution, you should be aware that this script then can directly modify the environment of your current shell. Also it is not possible to pass arguments anymore.
Another way to do, is to implement your script as a function in bash.
function cdbm() {
cd whereever_you_want_to_go
echo "Arguments to the functions were $1, $2, ..."
}
This technique is used by autojump: http://github.com/joelthelion/autojump/wiki to provide you with learning shell directory bookmarks.
You can create a function like below in your .bash_profile and it will work smoothly.
The following function takes an optional parameter which is a project.
For example, you can just run
cdproj
or
cdproj project_name
Here is the function definition.
cdproj(){
dir=/Users/yourname/projects
if [ "$1" ]; then
cd "${dir}/${1}"
else
cd "${dir}"
fi
}
Dont forget to source your .bash_profile
This should do what you want. Change to the directory of interest (from within the script), and then spawn a new bash shell.
#!/bin/bash
# saved as mov_dir.sh
cd ~/mt/v3/rt_linux-rt-tools/
bash
If you run this, it will take you to the directory of interest and when you exit it it will bring you back to the original place.
root#intel-corei7-64:~# ./mov_dir.sh
root#intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root#intel-corei7-64:~#
This will even take you to back to your original directory when you exit (CTRL+d)
I did the following:
create a file called case
paste the following in the file:
#!/bin/sh
cd /home/"$1"
save it and then:
chmod +x case
I also created an alias in my .bashrc:
alias disk='cd /home/; . case'
now when I type:
case 12345
essentially I am typing:
cd /home/12345
You can type any folder after 'case':
case 12
case 15
case 17
which is like typing:
cd /home/12
cd /home/15
cd /home/17
respectively
In my case the path is much longer - these guys summed it up with the ~ info earlier.
As explained on the other answers, you have changed the directory, but only within the sub-shell that runs the script. this does not impact the parent shell.
One solution is to use bash functions instead of a bash script (sh); by placing your bash script code into a function. That makes the function available as a command and then, this will be executed without a child process and thus any cd command will impact the caller shell.
Bash functions :
One feature of the bash profile is to store custom functions that can be run in the terminal or in bash scripts the same way you run application/commands this also could be used as a shortcut for long commands.
To make your function efficient system widely you will need to copy your function at the end of several files
/home/user/.bashrc
/home/user/.bash_profile
/root/.bashrc
/root/.bash_profile
You can sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile to edit/create those files quickly
Howto :
Copy your bash script code inside a new function at the end of your bash's profile file and restart your terminal, you can then run cdd or whatever the function you wrote.
Script Example
Making shortcut to cd .. with cdd
cdd() {
cd ..
}
ls shortcut
ll() {
ls -l -h
}
ls shortcut
lll() {
ls -l -h -a
}
If you are using fish as your shell, the best solution is to create a function. As an example, given the original question, you could copy the 4 lines below and paste them into your fish command line:
function proj
cd /home/tree/projects/java
end
funcsave proj
This will create the function and save it for use later. If your project changes, just repeat the process using the new path.
If you prefer, you can manually add the function file by doing the following:
nano ~/.config/fish/functions/proj.fish
and enter the text:
function proj
cd /home/tree/projects/java
end
and finally press ctrl+x to exit and y followed by return to save your changes.
(NOTE: the first method of using funcsave creates the proj.fish file for you).
You need no script, only set the correct option and create an environment variable.
shopt -s cdable_vars
in your ~/.bashrc allows to cd to the content of environment variables.
Create such an environment variable:
export myjava="/home/tree/projects/java"
and you can use:
cd myjava
Other alternatives.
Note the discussion How do I set the working directory of the parent process?
It contains some hackish answers, e.g.
https://stackoverflow.com/a/2375174/755804 (changing the parent process directory via gdb, don't do this) and https://stackoverflow.com/a/51985735/755804 (the command tailcd that injects cd dirname to the input stream of the parent process; well, ideally it should be a part of bash rather than a hack)
It is an old question, but I am really surprised I don't see this trick here
Instead of using cd you can use
export PWD=the/path/you/want
No need to create subshells or use aliases.
Note that it is your responsibility to make sure the/path/you/want exists.
I have to work in tcsh, and I know this is not an elegant solution, but for example, if I had to change folders to a path where one word is different, the whole thing can be done in the alias
a alias_name 'set a = `pwd`; set b = `echo $a | replace "Trees" "Tests"` ; cd $b'
If the path is always fixed, the just
a alias_name2 'cd path/you/always/need'
should work
In the line above, the new folder path is set
This combines the answer by Serge with an unrelated answer by David. It changes the directory, and then instead of forcing a bash shell, it launches the user's default shell. It however requires both getent and /etc/passwd to detect the default shell.
#!/usr/bin/env bash
cd desired/directory
USER_SHELL=$(getent passwd <USER> | cut -d : -f 7)
$USER_SHELL
Of course this still has the same deficiency of creating a nested shell.

my_script throwing an error of bash: /home/usr/bin/my_sript: bin/bash/ bad interpreter: No such file or directory. How can I correct this error?

First and foremost the script is a 'hello world' script and it's stored in ~/jared/bin. Here's the script:
#!bin/bash
echo "hello world"
Based on this question here, I tried:
The file is executable? I used:
chmod 755 my_script
I ran the following commands, and here is the output:
which bash
/bin/bash
and finally,
echo $PATH
/home/jared/bin:/home/jared/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin
The file endings are UNIX as I wrote the script in VIM. However to be safe, I wrote additional 'hello world' scripts in Sublime and Atom and received the same error when I ran them.
I even tried running dos2unix on the file.
The script will execute when ran directly from the directory and will execute in any directory if I type bash hello_world
However it throws the error if I use ./
I don't know if this will help, but it seems relevant: I can use tab autocomplete on the script if I don't preface it with bash or ./
I fear, I'm making a really stupid mistake here, hopefully someone is prepared to make me feel incredibly silly today. Thanks!
The first line of your script should be
#!/bin/bash
^
It needs to be #! followed by an absolute path to bash. Note the slash before /bin.
first line should look like:
#!/bin/bash
you forgot the '/' after '!' so the system cannot find correct (absolute) path to bash

"cannot execute binary file" when trying to run a shell script on linux

I am very new to linux and shell scriprting.
I am trying to run a shellscript from secure shell (ssh) on linux using following commands:
chmod +x path/to/mynewshell.sh
sh path/to/mynewshell.sh
I get this error:
path/to/mynewshell.sh: path/to/mynewshell.sh: cannot execute binary file.
Tried using this command:
bash path/to/mynewshell.sh
I get the same error.
Tried with this command: su - myusername sh path/to/mynewshell.sh
It is asking for my password and giving me this error: no such file or directory.
1.The result of cat -v path/to/mynewshell.sh is:
^#^#^#^#^#^#^#^#Rscript "$dir"/diver_script.R
done
2.When tried 'less path/to/mynewshell.sh' i got this on my terminal:
#!/bin/bash/Rscript^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#
for dir in /path/to/* ; do
^#^#^#^#^#^#^#^#Rscript "$dir"/myRscript.R
done
3.When i ran file path/to/mynewshell.sh : i got this "Bourne-Again shell script text executable"
Please give any advice on how I can try executing the shellscript.
chmod -x removes execution permission from a file. Do this:
chmod +x path/to/mynewshell.sh
And run it with
/path/to/mynewshell.sh
As the error report says, you script is not actually a script, it's a binary file.
I was getting the same error running my shell script through a bash interpreter in PowerShell. I ran dos2unix myscript.sh on the shell script, and now it runs ok.
From a proposed duplicate:
run_me.sh.xz: run_me.sh.xz: cannot execute binary file
This is because the file is compressed, as indicated by the .xz extension. You need to remove the compression before the file can be used.
xz -d ./run_me.sh.xz
chmod +x ./run_me.sh # probably not necessary if you already did that before
./run_me.sh
Other compression schemes like gzip (.gz extension), bzip2 (.bz2 extension) etc behave similarly; you just have to know the name of the command to uncompress it, which is of course usually easy to google.
To anyone else having the problem i had.
i was trying to run a 16 bit unicode text file converted to a shell script, this doesn't work as all 16 bit unicode text files have a 0xFFFE marker at the start making mac os not like the file and this gives the “cannot execute binary file” error.
open the text file click on "Format" at the top, go down to "Make Plain Text" click it.
open your terminal type chmod 777 /path/to/file.sh
put in terminal: /path/to/file.sh to run it
That script is simply not a shell script.
A shell script is usually readable and contains shell code.
The output your cat command shows looks indeed like it's a binary of some sort.
As some note, it might be because of a file conversion issue when copying but it looks more like an actual binary to me.
You can check what it is identified as with the file command so:
file path/to/mynewshell.sh
Just start with a clean script and rewrite the code, it looks like you just want to run some R scripts in a directory?
Make sure the R scripts point to the right R script executioner.
In my case I had a bash script that would not execute. The file was originally generated from a find ... -print0 command. Leaving a \0 character the script, removing that character solved my problem.

Can't run a script

I tried to create a script in linux, on a Synology server over SSH
so I wrote a file test.sh
#!/bin/bash
echo "this is a test"
I saved the file.
after that I did
chmod 755 test.sh
the I did
./test.sh
then i got this error
-ash "./test.sh" is not found
the file was created in
/root
I don't understand
Your shell (ash?) is trying to execute your script and is getting an ENOENT (no such file or directory) error code back. This can refer to the script itself, but in this case it refers to the interpreter named in the #! line.
That is, /bin/bash does not exist and that's why the script couldn't be started.
Workaround: Install bash or (if you don't need any bash specific features) change the first line to #!/bin/sh.
This is one of the quirks with hash bang programs. If the interpreter is not found (i.e. the program interpreting the script), you don't get a completely useful error like /bin/bash: no such file, but a completely useless and misleading test.sh: not found.
If this isn't in the Unix Hater's Handbook, it should be. :-)
You can either use #!/bin/sh or #!/path/to/bash or #!/usr/bin/env bash (which searches PATH for bash).

Bash script: bad interpreter

Question: I get this error message:
export: bad interpreter: No such file or directory
when I execute this bash script:
#!/bin/bash
MONO_PREFIX=/opt/mono-2.6
GNOME_PREFIX=/opt/gnome-2.6
export DYLD_LIBRARY_PATH=$MONO_PREFIX/lib:$DYLD_LIBRARY_PATH
export LD_LIBRARY_PATH=$MONO_PREFIX/lib:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=$MONO_PREFIX/include:$GNOME_PREFIX/include
export ACLOCAL_PATH=$MONO_PREFIX/share/aclocal
export PKG_CONFIG_PATH=$MONO_PREFIX/lib/pkgconfig:$GNOME_PREFIX/lib/pkgconfig
PATH=$MONO_PREFIX/bin:$PATH
PS1="[mono-2.6] \w # "
But the bash path seems to be correct:
asshat#IS1300:~/sources/mono-2.6# which bash
/bin/bash
asshat#IS1300:~# cd sources/
asshat#IS1300:~/sources# cd mono-2.6/
asshat#IS1300:~/sources/mono-2.6# ./mono-2.6-environment
export: bad interpreter: No such file or directory
asshat#IS1300:~/sources/mono-2.6# ls
download mono-2.4 mono-2.4-environment mono-2.6 mono-2.6-environment
asshat#IS1300:~/sources/mono-2.6# cp mono-2.6-environment mono-2.6-environment.sh
asshat#IS1300:~/sources/mono-2.6# ./mono-2.6-environment.sh
export: bad interpreter: No such file or directory
asshat#IS1300:~/sources/mono-2.6# ls
download mono-2.4-environment mono-2.6-environment
mono-2.4 mono-2.6 mono-2.6-environment.sh
asshat#IS1300:~/sources/mono-2.6# bash mono-2.6-environment
asshat#IS1300:~/sources/mono-2.6#
What am I doing wrong? Or is this a Lucid Lynx bug?
I did chmod + x
The first line, #!/bin/bash, tells Linux where to find the interpreter. The script should also be executable with chmod +x script.sh, which it appears you did.
It is highly likely that you created this file with a windows editor, which will place a <cr><lf> at the end of each line. This is the standard under dos / windows. OS X will place a <cr> at the end of each line. However, under Unix / Linux, the standard is to just put a <lf> at the end of the line.
Linux is now looking for a file called /bin/bash<cr> to interpret the file,
where <cr> is a carriage return character, which is a valid file character under Linux. Such a file doesn't exist. Hence the error.
Solution: Edit the file with an editor on Linux and get rid of the extra <cr>. One tool that usually works when the file is edited on Windows is dos2unix.
Could the script be using Dos newlines?
Try running dos2unix on it.
It looks like things have been configured to override the export builtin somehow. This can be done via an exported function or the enable builtin, for example. Try putting type export in the script to check. If you are setting BASH_ENV, you probably shouldn't.
If bash is called as sh, it enables POSIX mode and does not allow export to be overridden with a function, as required by POSIX. Likewise, most other shells installed as /bin/sh follow POSIX in this and/or do not allow the execution environment of a script to be messed up so strongly as through importing functions from the environment.
By the way, the script seems designed to be sourced, i.e. . ./mono-2.6-environment instead of ./mono-2.6-environment.
Had the same problem. Used brute force:
/bin/sh /full/path/to/configure --options
& this did the trick
(Of course I'd like to know why)
I encountered a similar error but in my case I forgot to add / before bin and I was encountering the bad interpreter error. Also tried to do
sudo apt-get install dos2unix -y package.
I was using this originally :
#! bin/bash ( i was missing / before bin )
Double check the path as well.
This could be a case of a shebang with homoglyphic unicode characters. In other words, you may have invisible or look-alike characters in the shebang which don't actually represent the string #!/bin/bash. Try looking at the characters in a hex editor.
what worked for me was when dos2Unix wasn't on the system I was working with:
sed -i s/{ctrl+v}{ctrl+m}// filename
This happens sometimes when file system goes funny.
Try to move or rename the file.
If you see "Stale file handle" error this is your problem.
e.g. happened us with CentOS docker
$ ./test.sh
-bash: ./test.sh: /bin/bash: bad interpreter: Invalid argument
$ ls -alstr test.sh
20 -r-xr-xr-x 0 omen omen 17874 Jun 20 01:36 test.sh
$ cp test.sh testcopy.sh
$ ./testcopy.sh
Happy Days
$ mv test.sh footest.sh
mv: cannot move ‘test.sh’ to ‘footest.sh’: Stale file handle
$ rm test.sh
rm: cannot remove ‘test.sh’: Stale file handle
You can copy the file and read it.
But not move it!
Nor remove it.
Some weird docker file-system thing maybe.
Solution: re-create the docker container OR maybe file system repair disk would help
OR of course format c: :-D :-o

Resources