use text and use as command? - linux

i whant to build a script to extract the word from a file in a command:
for example:
in my file i keep my username , how can i export the username without knowing the username as part of my command , which my command is : suspend here should be the word exported?
From my file which has the text inside "JOHN" how can i tell the command : suspend that the username is JOHN ?
how can i cat/grep/sed the text from the file as part of command :
something like suspend |cat file , i have try that but the suspend command does not take the username , so there should be something different .
my ideea where like this
#!/bin/sh
username=cat my-file;
suspend $username ,
but i had no succes , because my $username is not display from the cat , the cat is shows it but thats all that is doing.

Use the following syntax
username=$(cat my-file)
you might also use backquotes like
username=`cat my-file`
but the $(...) notation is preferable: it can be nested and is more readable.
Please read the Advanced Bash Scripting Guide (it will teach you a lot, even if it can be criticized)
Your usage of suspend is incorrect, and I don't understand what you want to do with it. What would suspending a user mean to you? Perhaps you want to use pgrep or pkill (to kill all the processes of that user, which I feel is too harsh)...?

The command to read a line is, shockingly, named "read":
$ cat file
John
$ IFS= read -r username < file
$ echo "$username"
John
"cat" is the command to concatenate files.
Setting IFS= and using the -r arg to read are so that read handles leading white space and/or backslashes as-is rather then interpreting them. If you KNOW your file can never contain those or you want read to strip leading white space and/or interpret backslashes than you can get rid of those.

Related

How do I pass ">>" or "<<" to my script without the terminal trying to interpret it as me either appending to something or getting stdin?

My python script can take a series of bitwise operators as one of its arguments. They all work fine except for "=<<" which is roll left, and "=>>" which is roll right. I run my script like ./script.py -b +4,-4,=>>10,=<<1, where anything after -b can be any combination of similar operations. As soon as the terminal sees "<<" though, it just drops the cursor to a new line after the command and asks for more input instead of running the script. When it sees ">>", my script doesn't process the arguments correctly. I know it's because bash uses these characters for a specific purpose, but I'd like to get around it while still using "=>>" and "=<<" in my arguments for my script. Is there any way to do it without enclosing the argument in quotation marks?
Thank you for your help.
You should enclose the parameters that contain special symbols into single quotation marks (here, echo represents your script):
> echo '+4,-4,=>>10,=<<1'
+4,-4,=>>10,=<<1
Alternatively, save the parameters to a file (say, params.txt) and read them from the file onto the command line using the backticks:
> echo `cat params.txt`
+4,-4,=>>10,=<<1
Lastly, you can escape some offending symbols:
> echo +4,-4,=\>\>10,=\<\<1
+4,-4,=>>10,=<<1

Unix: What does cat by itself do?

I saw the line data=$(cat) in a bash script (just declaring an empty variable) and am mystified as to what that could possibly do.
I read the man pages, but it doesn't have an example or explanation of this. Does this capture stdin or something? Any documentation on this?
EDIT: Specifically how the heck does doing data=$(cat) allow for it to run this hook script?
#!/bin/bash
# Runs all executable pre-commit-* hooks and exits after,
# if any of them was not successful.
#
# Based on
# http://osdir.com/ml/git/2009-01/msg00308.html
data=$(cat)
exitcodes=()
hookname=`basename $0`
# Run each hook, passing through STDIN and storing the exit code.
# We don't want to bail at the first failure, as the user might
# then bypass the hooks without knowing about additional issues.
for hook in $GIT_DIR/hooks/$hookname-*; do
test -x "$hook" || continue
echo "$data" | "$hook"
exitcodes+=($?)
done
https://github.com/henrik/dotfiles/blob/master/git_template/hooks/pre-commit
cat will catenate its input to its output.
In the context of the variable capture you posted, the effect is to assign the statement's (or containing script's) standard input to the variable.
The command substitution $(command) will return the command's output; the assignment will assign the substituted string to the variable; and in the absence of a file name argument, cat will read and print standard input.
The Git hook script you found this in captures the commit data from standard input so that it can be repeatedly piped to each hook script separately. You only get one copy of standard input, so if you need it multiple times, you need to capture it somehow. (I would use a temporary file, and quote all file name variables properly; but keeping the data in a variable is certainly okay, especially if you only expect fairly small amounts of input.)
Doing:
t#t:~# temp=$(cat)
hello how
are you?
t#t:~# echo $temp
hello how are you?
(A single Controld on the line by itself following "are you?" terminates the input.)
As manual says
cat - concatenate files and print on the standard output
Also
cat Copy standard input to standard output.
here, cat will concatenate your STDIN into a single string and assign it to variable temp.
Say your bash script script.sh is:
#!/bin/bash
data=$(cat)
Then, the following commands will store the string STR in the variable data:
echo STR | bash script.sh
bash script.sh < <(echo STR)
bash script.sh <<< STR

Pass content from .txt file as argument for bash script?

I need to "Write a script to add users to your system in which the names of the users are given to script as an argument n (in?, spell error by professor) a text file of the format
Last_Name First_Name Middle_Initial Group
(rest of instructions FYI) Your script should create unique user names of up to 8 characters, and generate
random passwords for the users. The users should be assigned home directories
depending on the group they are in. You can assume that the users will belong to
Management (“mgmt”), Employee (“empl”) or Temporary (“temp”) and that their
respective directories are under these group names in /home. For e.g., if John Doe is
in “mgmt.”, and his user name is jdoe1234, then his home directory should be in
/home/mgmt/jdoe1234. Lock the home directories such that no one else has
permissions to the home directories than the users themselves.
Your script should generate a file called users.txt that contains the following columns:
Last Name First Name UID Password
which can be used to distribute the user names and passwords to the users.
The first part (not in italics) is what confuses me. If I understand his wording correctly, he wants me to take text from a separate .txt file and use it as the arguments for my script? With the idea of
./file.sh arg1 arg2 arg3 arg4
except those args are going to be the first four words in the .txt file? Say, if the .txt file contains "Doe John A empl", then it would be like typing
./file.sh arg1 arg2 arg3 arg4
Here's my attempt so far (I've actually tried other things but this is what I have on screen right now, sort of what I started out with):
#!/bin/bash
echo "$(cat file.txt)"
lname=$(echo $1|head -c 3)//to make username use first 3 letters of last name
fname=$(echo $2|head -c 1)//to make username use first letter of first name
mname=$3
group=$4
echo "$lname$fname$mname$group"
As of right now, anything below the first line doesn't do anything. I got the first line from command line arguments from a file content and I used it because I thought it would let me use the content from a .txt file as arguments but it's clearly not doing that. It's just outputting the content of it, not using letting me using each word as an argument. Not sure what to do. Any help? I thought this wasn't going to be very difficult as I started writing the script assuming the user would provide the arguments but I reread the first part of the instructions and assume he wants them to be taken from a separate .txt file.
$(command) returns the output of the command. If you do $(cat some_file) it will return the text of the file. You can use it to give the content of a file as an argument doing:
cmd1 $(cat args_file)
So when you use echo $(cat file.txt), you get the same output as if you were using cat file.txt because cat sends the content of the file to echo which displays it to the standard output.
$n means argument n passed to the script ($0 being the name of the script). Here you simply have to provide one argument, the name of the file. So $2, $3 and $4 will not contain anything.
So, from the file you can only get a string with the names with $names=$(cat $1). In order to get each field separately, you can use cut:
lname=$(cut -d \ -f 1 $1)
fname=$(cut -d \ -f 2 $1)
mname=$(cut -d \ -f 3 $1)
group=$(cut -d \ -f 4 $1)
NOTES:
The symbol for comments in shell is # NOT //.
head displays the first lines of a file, head -c the first bytes. It does not cut the file.
What I understood as the problem is that:
Firstly: You want to pass the contents of a text file as an input/argument to a shell script.
There could be other ways, but I suggest the following:
./YourScriptFile.sh $(cat YourInputFile.txt)
Secondly: You want to use its contents.
I would suggest to use the following inside your script file:
$1, $3, $4, ..., $n
to access the:
1st, 2nd, 3rd, ..., nth
tokens from the input file (irrespective of new lines).
Finally: You want to make username use first 3 letters of last name or in other words you want to extract characters from a string.
Once you have tokens it's just simple. I would suggest the following:
FirstTwoChars_of_FirstToken=${1:0:2}
FirstTwoChars_of_SeventhToken=${7:0:2}
Or
LastTwoChars_of_FirstToken=${1:7:9}
# if the first token is "FirstName" it would return you "me"
Hope this would help you to improve your code.
As a footnote: Your code will become: (# is used for comments here)
#!/bin/bash
lname=$(1:0:3) #to make username use first 3 letters of last name
fname=$(2:0:1) #to make username use first letter of first name
mname=$3
group=$4
echo "$lname$fname$mname$group"
Now you will have to execute your shell script as mentioned above.

egrep command with piped variable in ssh throwing No Such File or Directory error

Ok, here I'm again, struggling with ssh. I'm trying to retrieve some data from remote log file based on tokens. I'm trying to pass multiple tokens in egrep command via ssh:
IFS=$'\n'
commentsArray=($(ssh $sourceUser#$sourceHost "$(egrep "$v" /$INSTALL_DIR/$PROP_BUNDLE.log)"))
echo ${commentsArray[0]}
echo ${commentsArray[1]}
commax=${#commentsArray[#]}
echo $commax
where $v is something like below but it's length is dynamic. Meaning it can have many file names seperated by pipe.
UserComments/propagateBundle-2013-10-22--07:05:37.jar|UserComments/propagateBundle-2013-10-22--07:03:57.jar
The output which I get is:
oracle#172.18.12.42's password:
bash: UserComments/propagateBundle-2013-10-22--07:03:57.jar/New: No such file or directory
bash: line 1: UserComments/propagateBundle-2013-10-22--07:05:37.jar/nouserinput: No such file or directory
0
Thing worth noting is that my log file data has spaces in it. So, in the code piece I've given, the actual comments which I want to extract start after the jar file name like : UserComments/propagateBundle-2013-10-22--07:03:57.jar/
The actual comments are 'New Life Starts here' but the logs show that we are actually getting it till 'New' and then it breaks at space. I tried giving IFS but of no use. Probably I need to give it on remote but I don't know how should I do that.
Any help?
Your command is trying to run the egrep "$v" /$INSTALL_DIR/$PROP_BUNDLE.log on the local machine, and pass the result of that as the command to run via SSH.
I suspect that you meant for that command to be run on the remote machine. Remove the inner $() to get that to happen (and fix the quoting):
commentsArray=($(ssh $sourceUser#$sourceHost "egrep '$v' '/$INSTALL_DIR/$PROP_BUNDLE.log'"))
You should use fgrep to avoid regex special interpretation from your input:
commentsArray=($(ssh $sourceUser#$sourceHost "$(fgrep "$v" /$INSTALL_DIR/$PROP_BUNDLE.log)"))

change multiple files commandline

I have separated some tracks from mp3 mixes using mp3splt.
BASH: (mp3splt -c('**!!***use .cue file***!!**') [cuefile.cue] [nonstopmix.mp3] ~for anyone interested, is in the Ubu repos~)
And I ended up with these filenames: "Antares" - 01 - "Xibalba".mp3 which is not a format I prefer, now I've made it a little project to change them with a shell script but its more difficult than I anticipated.
I want to change the filename from:
"Antares" - 01 - "Xibalba".mp
to:
01-Antares_-_Xibalba.mp3
so far I've used :
for var in *.mp3; do mv $var {var/"/}; done
and I could repeat that until I'm through, delete the 0x number and add one but I'd like to do it more efficient.
Could anyone give me a pointer (!not a script!) ?
I'd still like to write it myself but there's so much options that I'm a bit lost.
so far I thought to use this program flow:
read all the filenames containing .mp3 and declare as variable $var
strip $var from quotes
select 0x number, append delimiter _ (0x_)
move 0x_ to the beginning of the string
select remaining ' - - ' and change to '-'
done
which bash programs to use? especially changing the 0x puzzles me cuz I need a loop which increments this number and test if it is present in the filename variable and then it has to be changed.
It is easy to do in python 2.x. You can use this logic in any language you want.
import string
a=raw_input('Enter the name of song')
a=a.replace('"', "")
a=a.replace('.mp', ' .mp3')
words = a.split()
print words[2]+'-'+words[0]+'_-_'+words[4]+words[5]
Logic:
I removed ", then make .mp to .mp3, then splitted the string, which created a list ( array ) and then printed the elements according to need.
Try doing this :
rename -n 's/"(\w+)"\s+-\s*(\d+)\s*-\s*"(\w+)"\.mp/$2-$1_-_$3.mp3/' *mp
from the shell prompt. It's very useful, you can put some perl tricks like I does in a substitution.
You can remove the -n (dry-run mode switch) when your tests become valids.
There are other tools with the same name which may or may not be able to do this, so be careful.
If you run the following command (linux)
$ file $(readlink -f $(type -p rename))
and you have a result like
.../rename: Perl script, ASCII text executable
then this seems to be the right tool =)
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo update-alternatives --set rename /path/to/rename
Last but not least, this tool was originally written by Larry Wall, the Perl's dad.

Resources