cat a file to a variable - bash

Assuming the name of my script is myscript.sh and my current directory is /Users/scripts/ I'm trying to do the following:
localScript=$(cat ./myscript.sh)
I get the following error:
#!/bin/sh not found
I can't seem to figure out how to do this, but I assume its not working because $() is creating a subshell that has a different pwd and thus cannot find my file.
I've also tried using various combinations of pwd but I'm having trouble with this method as well.

On OSX I've done the following:
$ vim test.sh
and typed in the following:
#!/bin/sh
localScript=$(cat ./test.sh)
echo $localScript
and then,
$ chmod +x test.sh
$ ./test.sh
which gives the following output:
#!/bin/sh localScript=$(cat ./test.sh) echo $localScript
Maybe the above will help you spot your error.

Related

symlink script does not exist on startx

The problem I am having is running a symbolic link called example inside a script (example points to b.sh).
Running $ example from a terminal appends the message scriptB was found to the log. The same happens if I run $ ./b.sh from $HOME. However, example is not executed while starting up X.
I have created the following minimal setup on my system to imitate my problem.
a.sh
#!/bin/bash
type example ||
echo "error: example could not be found." >>"$HOME/example.log"
~/b.sh
b.sh
#!/bin/bash
echo "scriptB was found" >>"$HOME/example.log"
.xinitrc
#!/bin/sh
if [ -x "$HOME/a.sh" ]; then
bash ~/a.sh
fi
The minimal setup
X executes a.sh
link created with $ ln -s ~/a.sh ~/.local/bin/example
scripts made executable with $ chmod u+x a.sh b.sh and verified to be executable with ls -l
appended $HOME/.local/bin to my PATH environment variable in .bashrc
The log after restarting X (or rebooting) is:
error: example could not be found.
scriptB was found
.... ~/.local/bin/example
So add that path to PATH.
#!/bin/sh
export PATH="$HOME/.local/bin:$PATH"
example

How to translate an alias into a real file?

Most of the time, an alias works well, but some times, the command is executed by other programs, and they find it in the PATH, in this situation an alias not works as well as a real file.
e.g.
I have the following alias:
alias ghc='stack exec -- ghc'
And I want to translate it into an executable file, so that the programs which depending on it will find it correctly. And the file will works just like the alias does, including how it process it's arguments.
So, is there any tool or scripts can help doing this?
Here is my solution, I created a file named ghc as following:
#!/bin/sh
stack exec -- ghc "$#"
The reason why there is double quote around $# is explained here: Propagate all arguments in a bash shell script
So, is there any tool or scripts can help doing this?
A lazy question for a simple problem... Here's a function:
alias2script() {
if type "$1" | grep -q '^'"$1"' is aliased to ' ; then
alias |
{ sed -n "s#.* ${1}='\(.*\)'\$##\!/bin/sh\n\1 \"\${\#}\"#p" \
> "$1".sh
chmod +x "$1".sh
echo "Alias '$1' hereby scriptified. To run type: './$1.sh'" ;}
fi; }
Let's try it on the common bash alias ll:
alias2script ll
Output:
Alias 'll' hereby scriptified. To run type: './ll.sh'
What's inside ll.sh:
cat ll.sh
Output:
#!/bin/sh
ls -alF "${#}"

How to get parent folder of executing script in zsh?

In bash i get the executing script's parent folder name by this line
SCRIPT_PARENT=`readlink -f ${BASH_SOURCE%/*}/..`
Is there any way to achieve this in zsh in a way that works both in zsh and bash?
Assume i have got a file /some/folder/rootfolder/subfolder/script with the contents:
echo `magic-i-am-looking-for`
I want it to behave this way:
$ cd /some/other/folder
$ . /some/folder/rootfolder/subfolder/script
/some/folder/rootfolder
$ . ../../folder/rootfolder/subfolder/script
/some/folder/rootfolder
$ cd /some/folder/rootfolder
$ . subfolder/script
/some/folder/rootfolder
$ cd subfolder
$ . script
/some/folder/rootfolder
This should work in bash and zsh. My first implements this behavior, but does due to $BASH_SOURCE not work in zsh.
So basically its:
Is there a way to emulate $BASH_SOURCE in zsh, that also works in bash?
I now realized that $0 in zsh behaves like $BASH_SOURCE in bash. So using $BASH_SOURCE when available and falling back to $0 solves my problem:
${BASH_SOURCE:-$0}
There is a little zsh edge case left, when sourcing from $PATH like:
zsh> cat ../script
echo \$0: $0
echo \$BASH_SOURCE: $BASH_SOURCE
echo '${BASH_SOURCE:-$0}:' ${BASH_SOURCE:-$0}
zsh> . script
$0: script
$BASH_SOURCE:
${BASH_SOURCE:-$0}: script
bash> . script
$0: bash
$BASH_SOURCE: /home/me/script
${BASH_SOURCE:-$0}: /home/me/script
I could do a which script but this would not play nice with other cases
While it would be easy to do this in zsh, it is just as easy to use pure bash which is able to be evaluated in zsh. If you cannot use any command that may or may not be on your path, then you can only use variable alteration to achieve what you want:
SCRIPT_SOURCE=${0%/*}
This is likely to be a relative path. If you really want the full path then you will have to resort to an external command (you could implement it yourself, but it would be a lot of work to avoid using a very available command):
SCRIPT_SOURCE=$(/bin/readlink -f ${0%/*})
This doesn't depend on your $PATH, it just depends on /bin/readlink being present. Which it almost certainly is.
Now, you wanted this to be a sourced file. This is fine, as you can just export any variable you set, however if you execute the above then $0 will be the location of the sourced file and not the location of the calling script.
This just means you need to set a variable to hold the $0 value which the sourced script knows about. For example:
The script you will source:
echo ${LOCATION%/*}
The script that sources that script:
LOCATION=$0
<source script here>
But given that the ${0%/*} expansion is so compact, you could just use that in place of the script.
Because you were able to run the command from your $PATH I'll do something like that:
SCRIPT_PARENT=$(readlink -f "$(which $0)/..")
Is that your desired output?

cat command in unix shell script

I have 2 lines of code
1) With the following code:
for i in `ls *.properties`; do cat $i; done
I get the error:
cat: file_name.properties: No such file or directory.
2) On the other hand:
for i in *.properties; do cat $i; done
Works fine!
I thought both were the same. Can someone help me understand the difference between the two? Using bash shell.
What does the following command print?
cat -v <<< `ls *.properties`
I guess the problem is, that ls is a strange alias, e.g. something like
ls='ls --color'
Edit: I have seen this before. The alias should be: alias ls='ls --color=auto'
Most probably there is a directory which matches *.properties. Then ls will output the files in this directory without the directory name. Then the cat will not find the given filename.
So please check, whether file_name.properties is in the actual directory or in some subdirectory.
EDIT
To reproduce the problem you can try this:
# cd /tmp
# mkdir foo.properties
# touch foo.properties/file_name.properties
# for i in `ls *.properties`; do cat $i; done
cat: file_name.properties: No such file or directory

Space in directory name creating problem

I am trying to build some code and the location where the compiler is present has a space in it 'blahblah/Source Code/blahblah' .I am not sure how to add this to the environment variable.I use bash and tried to use the normal
export PATH="$PATH:/blahblah/Source Code/blahblah"
but it doesnt seem to work(I also tried using \before spaces).Throws me errors like No such file or directory.Am I missing out on something?
I just did a little experimentation on my own:
$ mkdir 'Source Code'
$ cd Source\ Code/
$ vim testme.pl
$ chmod 755 testme.pl
$ cat testme.pl
#! /usr/bin/perl
print "I worked\n";
$ ./testme.pl
I worked
$ cd ..
$ export PATH="$PATH:/home/bchittenden/Source Code"
$ testme.pl
I worked
This indicates that the problem is not the whitespace in $PATH... bash seems to handle that correctly... you'll have to give us more information.

Resources