bash-scripting interview questions
Top bash-scripting frequently asked interview questions
If I have a symbolic link /var/opt/foo
created with ln -fs /path/to/target/dir foo
. How can I in a script that sees only the link get /path/to/target/dir
?
What I want to achieve in the script is rm -rf /path/to/target/dir
before I do ln -fs /path/to/another/dir foo
.
Source: (StackOverflow)
What's the simplest way to remove lines from one file matched with lines from another file? For example, if I have the following files:
file1.csv:
u2@domain.com
file2.csv:
1,u1@domain.com,somehash1
2,u2@domain.com,somehash2
3,u3@domain.com,somehash3
As a result I'd like to have file3.csv:
1,u1@domain.com,somehash1
3,u3@domain.com,somehash3
What's the fastest way to solve this task? These files are a few GB in size.
Source: (StackOverflow)
i have to compare a number of files and I don't want to change the command in two places all the time. so i want to create an alias in bash.
alias gd='gvimdiff $1 dir/$1'
so that i can get
gvimdiff res.tex dir/res.tex
just by typing
gd res.tex
Source: (StackOverflow)
For example, I wanted to use the sort utility with the -t option to specify tab separators, but
sort -t "\t"
doesn't work.
Source: (StackOverflow)
I've just started getting deeper into shell scripting, and I've always just thrown my script in a file, marked it chmod +x
and then done /path/to/script.sh
and let whatever interpreter is the default have its way with it, which I assumed was zsh because that's what I used for my shell. Apparently it seems that it's just /bin/sh
by default, even if I execute the script from a zsh prompt, because I started putting zsh-specific stuff in my scripts and it's failing unless I run zsh /path/to/script.sh
.
To get to the point, here are my questions:
- Which shell executes scripts when there's no shebang line (
#!/path/to/shell
) at the beginning? I assume /bin/sh
but I can't confirm.
- What is considered "best practices" in terms of writing shell scripts that will run on any platform? (ok, this is sort of open-ended)
Is it possible to write a script that tries to use zsh and falls back to bash if zsh is not available? I've tried putting two shebang lines, like below, but it just errors with bad interpreter: /bin/zsh: no such file or directory
out if I try it on a machine without zsh.
#!/bin/zsh
#!/bin/bash
Source: (StackOverflow)
Why to the following two executions differ in output? (I need double quotes for variables in my eventual command)
$ sudo su -c "echo `cat /root/root_file`"
cat: /root/root_file: Permission denied
$ sudo su -c 'echo `cat /root/root_file`'
Yay, highly classified content!
Source: (StackOverflow)
I have a large number of file, some of which are very long. I would like to truncate them to a certain size if they are larger by removing the end of the file. But I only want to remove whole lines. How can I do this? It feels like the kind of thing that would be handled by the Linux toolchain but I don't know of the right command.
For example, say I have a 120,000 byte file with 300-byte lines and I'm trying to truncate it to 10,000 bytes. The first 33 lines should stay (9900 bytes) and the remainder should be cut. I don't want to cut at 10,000 bytes exactly, since that would leave a partial line.
Of course the files are of differing lengths and the lines are not all the same length.
Ideally the resulting files would be made slightly shorter rather than slightly longer (if the breakpoint is on a long line) but that's not too important, it could be a little longer if that' easier. I would like the changes to be made directly to files (well, possibly the new file copied elsewhere, the original deleted, and the new file moved, but that's the same from the user's POV). A solution that redirects data to a bunch of places and then back invites the possibility of corrupting the file and I'd like to avoid that...
Source: (StackOverflow)
Just trying to learn bash scripting a little.
My old bash version:
Bash version 3.2.53(1)-release...
I've updated my bash on mac os x yosemite with homebrew:
brew update
brew install bash
Then in terminal properties I’ve changed the standard shell path from /bin/bash
to /usr/local/bin/bash
(As I understand this is where the homebrew installs the updated bash).
Then I checked the result again (and seems like it's all good):
$ echo $BASH_VERSION
Bash version 4.0.33(0)-release...
But when I was trying to write a simple bash script:
#!/bin/bash
echo "Bash version ${BASH_VERSION}..."
for i in {0..10..2}
do
echo "Welcome $i times"
done
THE RESULT IS:
Bash version 3.2.53(1)-release...
Welcome {0..10..2} times
INSTEAD OF:
Bash version 4.0.33(0)-release...
Welcome 0 times
Welcome 2 times
Welcome 4 times
Welcome 6 times
Welcome 8 times
Welcome 10 times
Why the Bash version changes back to old one when I'm trying to execute script in the same shell??? This just freaks me out! Please someone explain me what's my problem)))
Source: (StackOverflow)
In my Bash-script I have to handle filenames with spaces. These are the important lines inside my script:
mp3file="/media/d/Music/zz_Hardcore/Sampler/Punk-O-Rama\ Vol.5\ \[MP3PRO\]/01\ -\ Nofx\ -\ Pump\ up\ the\ Valium.mp3"
echo "Command: mp3info -x `echo $mp3file`"
mp3info -x `echo $mp3file`
Unfortunately, the command does not work, because the filename is splitted:
mp3info: invalid option -- '\'
mp3info: invalid option -- '\'
Error opening MP3: /media/d/Music/zz_Hardcore/Sampler/Punk-O-Rama\: No such file or directory
Error opening MP3: Vol.5\: No such file or directory
Error opening MP3: \[MP3PRO\]/01\: No such file or directory
Error opening MP3: Nofx\: No such file or directory
Error opening MP3: Pump\: No such file or directory
Error opening MP3: up\: No such file or directory
Error opening MP3: the\: No such file or directory
Error opening MP3: Valium.mp3: No such file or directory
I also tried to add a custom IFS as i read on some forums:
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
# Script like above
IFS=$SAVEIFS
But this way, i'm getting the error
Error opening MP3: /media/d/Music/zz_Hardcore/Sampler/Punk-O-Rama\ Vol.5\ \[MP3PRO\]/01\ -\ Nofx\ -\ Pump\ up\ the\ Valium.mp3: No such file or directory
I tried quite a while now but i cannot get my script to work. What is strange is that if i'm running the same command that my script should create manually (echoing it inside my script) on the Shell, it actually works. But not inside my script. Any hints?
Source: (StackOverflow)
I need create log files that are essentially date stamps with prefix yp_
and suffix .log
, and a manipulated day number:
$ touch yp_$(echo "$(date +%Y%m%d)-10" | /usr/bin/bc -l).log
$ ls
yp_20150912.log # ... ok for today's date.
That's fine for today, but all hell breaks loose when the day's number is between 01 and 10 included. The result cannot be interpreted as a date stamp any longer.
E.g. just imagine that the day is the 8th of March, 2016, i.e. '20160308'.
How do I code the above to make sure that subtracting 10 days will produce not '20150298' but '20150227' ?
Also test yr answer with 19820103 ...
-- I looked at man date
.
-- apropos date
spews out 161 hits that I also reviewed.
Can somebody help with that one-liner?
Source: (StackOverflow)
I don't know if this is a bad thing, or what it means. My script still seems to work fine, but should I fix it?
#!/bin/sh
#This script will send text and maybe images to other computers via ssh and scp.
#Configuration files in same folder
source /Users/jacobgarby/Desktop/messaging/messages.cfg
TIME=$(date +"%H:%M:%S")
CONNECTED[0]="mainmini@192.168.1.65"
if [ -d messages.log ]; then
:
else
touch messages.log
fi
read MSG
if [ "$MSG" == "!help" ]; then
echo ; echo "!clear Clear's your personal chat log."
echo "!ban [usrname] Prevents a user from entering this chat IN DEV."
else
echo "$TIME | $USER | $MSG" >> messages.log; echo >> messages.log; echo >> messages.log
tail messages.log
fi
for CONNECTION in CONNECTED; do
echo "It works"
done
if [ "alerttype" == "notification"]; then
osascript -e 'display notification "You have recieved a message!" with title "Message"'
else
osascript -e 'display dialog "You have recieved a message!" with title "Message"'
fi
Source: (StackOverflow)
I'm running shell scripts from Jenkins, which kicks off shell scripts with the shebang options #!/bin/sh -ex
.
According to Bash Shebang for dummies?, -x
, "causes the shell to print an execution trace", which is great for most purposes - except for echos:
echo "Message"
produces the output
+ echo "Message"
Message
which is a bit redundant, and looks a bit strange. Is there a way to leave -x
enabled, but only output
Message
instead of the two lines above, e.g. by prefixing the echo command with a special command character, or redirecting output?
Source: (StackOverflow)
I have a series of files in a directory that I need to carry an action out on using a script. Once the action is done, then I want to keep a log that the file has been processed, so that the next time the script is run, it does not attempt to carry out the action again.
So lets say I can find all the files that should be processed like this:
for i in `find /logfolder -name '20*.log'` ; do
process_log $i
echo $i >> processedlogsfile
done
So I have a file containing the logs I have processed, and my goal would be to modify the for loop such that these processed logs are not processed a second time.
Doing a manual scan each time seems inefficient, particularly as the processedlogfiles gets bigger:
if grep -iq "$i" processdlogfiles ; then continue; fi
It would be good if these files could be excluded when setting up the for loop.
Note that the OS in question is a linux derivative, a managment appliance, with a limited toolset (no attr
command for example) and so no way to install additional utilities (well it is possible but not an option). Most common bash shell commands are available though.
Also, the filenames and locations of the processed files must remain where they are - they can't be altered to reflect their processed status
Source: (StackOverflow)
I apologize that this seems like such a dumb question, but I can't afford to screw it up.
I have a bunch of folders like so:
/users/me/foo/oops1
/users/me/foo/oops2
/users/me/foo/oops3
/users/me/foo/oops4
/users/me/foo/bar
Unfortunately, they aren't uniformly named like that, and there are hundreds of oops folders.
I intended to copy all the oops folders into bar. Is there an easy way to move all the oops folders into bar that won't result in some kind of recursive move problem?
It took several hours to copy the files. I'm hoping that the move will be much faster.
This is on a redhat linux server by the way. I only have ssh access.
I think if I do
cd foo
mv * bar
there will be a problem.
Source: (StackOverflow)
I am trying to make a modular script. I have several scripts/commands which are called from a single script.
I want to prefix the output of each separate command.
Examle:
My files are allcommands.sh / command1.sh / command2.sh
command1.sh outputs
file exists
file moved
command2.sh outputs
file copied
file emptied
allcommands.sh runs the scripts command1.sh and command2.sh
I want to prefix each output of these two scripts like this:
[command1] file exists
[command1] file moved
[command2] file copied
[command2] file emptied
Source: (StackOverflow)