Tag Info

New answers tagged

0

Consider a simpler example to see the difference: $ set "a b" c "d e" $ printf "%s\n" "$@" a b c d e The preceding is what you should use; it's simple, easy to understand, and correct. $ printf "%s\n" "$(echo $@)" a b c d e Here, $@ first expands unquoted (the quotes surrounding the command substitution are separate and not yet applied), so it's ...


0

For the third version, you want "$*" not "$@". Explanation To illustrate, let's set some positional arguments: $ set -- arg1 arg2 arg3 Now, let's read them out with your echo formulation: $ printf "%s\n" "$(echo $@)" arg1 arg2 arg3 Let's see what $@ does with them: $ printf "%s\n" "$@" arg1 arg2 arg3 The difference is that "$@" expands to three ...


0

With date it is only a two line bash calculation: #!/bin/bash month="$1" year="$2" read -r dow day < <(date -d "$year/$month/1 +1 month -1 day" "+%u %d") echo "Last working day of the month = $(( day - ( (dow>5)?(dow-5):0 ) ))" The math is: if dow (the day of the week) is bigger than 5, subtract (dow-5) from the day, else, leave day unchanged. ...


2

Rather than roll your own and have to cope with everything that can go wrong (host not responding, host stopping responding in the middle, user pressing Ctrl+C, error reporting, …), use one of the many existing tools to run a command on many machines over SSH. mussh -t 4 -H <(printf '%s\n' "${HOSTS[@]}") -c 'uname -a' pssh -t 4 -h <(printf '%s\n' ...


1

A typical way to do this is to use the trap command to tell the shell script to ignore SIGINT (generated by Control-C), and then to re-enable SIGINT in a subshell just before your command is run. #!/bin/sh trap "" INT for host in $(cat hostlist) do (trap - INT; ssh $host "long-running command") done


0

this may work grep -c ^the desired string filename wc -l thefile


2

You can try parsing your program's output with sed and executing the commands: $(./YOUR_PROGRAM | sed s/^.*==/rm/ | sed s/\ \(.*//) will execute (from your example) rm new_GS_calculation/selected/POSCAR_0011 rm new_GS_calculation/selected/POSCAR_0022 rm new_GS_calculation/selected/POSCAR_0027 rm new_GS_calculation/selected/POSCAR_0027 rm ...


1

A command like xyz=abc def ghi jkl means to run the def program with arguments ghi and jkl, and with environment variable xyz set to abc.  To set HOSTS to the string MACHINE1 MACHINE 2 you would need to say HOSTS="MACHINE1 MACHINE 2" (although I assume that you don't want to have a space between the second MACHINE and the 2.)  You could probably get ...


1

As @StéphaneChazelas mentions, you can use pgrep - from the man page: The pgrep command searches the process table on the running system and prints the process IDs of all processes that match the criteria given on the command line. SERVICE='Google Chrome' if pgrep -xq -- "${SERVICE}"; then echo running else echo not running fi


0

You need to quote "$SERVICE": SERVICE='Google Chrome' if ps ax | grep -v grep | grep "${SERVICE}" &> /dev/null; then echo running else echo not running fi


1

You can create a recursive script. eg in file /tmp/run #!/bin/bash depth=${1:-5} f(){ let depth-- if [ $depth -gt 0 ] then $0 $depth else sleep 10 fi } f then chmod +x /tmp/run and do /tmp/run 10.


1

In bash (and also shell which support brace expansion), you can do: printf '%s\n' "$(printf 'mytext%s\n\n' {1..71})" | paste -sd', ' - >out In POSIX shell: printf '%s\n' "$( n=1 while [ "$n" -le 71 ]; do printf 'mytext%s\n\n' "$n" n=$((n+1)) done )" | paste -sd', ' - >out


1

You just need to make sure you don't append a newline to the end of the output: just replace echo with either echo -n or printf. I'd recommend the latter as it's more portable.


0

Can this be written without width and max variables using my simple nested loop ? As below :- w=1 until [ $w -le 9 ] ; do until [ $w -eq 4 ] ; do w=`expr $w + 1` echo “$w” done echo “$w” done


0

width=4 max=9 decr=$(($width-1)) for w in $(seq $(($max-$decr))) do seq -s' ' $w $(($w+$decr)) done


0

Since you use bash you don't need two loops for that, one + brace expansion is enough: i=0; width=4; max=9 until [ $((i++)) -ge $((max-width+1)) ]; do eval echo {$i..$((i+width-1))} done Should work for any widths > 0, and starting points (including negative values). If you really like to use two loops just rewrite inner line with brace expansion.


1

Use bar1+=($(echo $foo | awk '{print$1}')) i.e., variable+=( value ) to add a value to an array.  Of course the code to use the bar1 array has to look something like for foo in "${bar1[@]}" do echo "$foo" done Of course you should always quote shell variables (e.g., "$foo" and "${bar1[@]}") unless you have a good reason not to, and you’re ...


-2

du path_to_your_files/*.jpg | awk '{ total += $1 }; END { print total }'


1

As you mentioned that it should be an automated shell script, at least for the two yum commands you would need to add -y so yum will assume an answer of "yes" for all questions it will ask. See the yum man page, relevant excerpt: -y, --assumeyes Assume yes; assume that the answer to any question which would be asked is yes. ...


2

One approach that would work is just appending to the end of the bashrc rather than syncing it. echo "PATH=\$PATH:~/bin" >> ~/.bashrc This will add ~/bin onto the PATH variable. In order to get this on a remote host you just need to call ssh first. You can use a for loop if you have lots of hosts. for host in host1 host2 host3;do ssh ...


3

Here's a summary of some of the drawbacks of: cat $file | cmd over < $file cmd First, a note: there are (intentionally for the purpose of the discussion) missing double quotes around $file above. In the case of cat, that's always a problem except for zsh; in the case of the redirection, that's only a problem for bash or for some other shells only ...


6

find will set its return code to non-zero if it saw an error. So you can do: if ! find ... then echo had an error >&2 fi | while ... (I'm not sure what you want to do with the find output). To collect all the error messages from find on stderr (file descriptor 2) you can redirect 2 to a file. Eg: if ! find ... 2>/tmp/errors then ...


0

Here is an alternative solution using find (should work if you aren't using bash). This solution will find all files and folders (see below for file-only version) with 3 or more characters that starts with the character 'l' recursively (see below for non-recursive) under where you execute it from. find . -regex '.*/l[^/][^/][^/]*' A non-recursive version ...


2

Bash globs Don't use regex. Use globs (assuming you are using bash). ls l??* Explanation ? stands for a single character. * stands for zero or more characters. Regex If you really wanted to use regex, you could use ls | grep "^l...*" Explanation . stands for a single character. .* stands for zero or more characters.


5

The snippet you provide is out of context, so it's difficult to say what it means in the larger scheme of what you are doing, but: set JUL = $today:e Creates a variable called JUL to the contents of the variable $today, using a tcsh or csh modifier (:e) to remove everything but the extension of $today. set CAL = $today:r Creates a variable called CAL ...


0

For a simple output printing sed -e 's/application:.*/application: RMAN/p' filename To modify the file directly sed -i 's/application:.*/application: RMAN/g' filename Also you can modify one by one in case you want to change a specific application: line. $ vim myjobs ~ ~ ~ ~ :%s/application: /application: RMAN/gc This will ask you line by line if ...


0

Assuming the example input you gave: sed -e 's/application:.*/application: RMAN/g' filename


4

Many tools can be handy: -n of grep is exactly what you are looking for. grep -n 'bla' file alternatively awk: awk '/bla/{print NR":"$0}' file alternatively perl: perl -ne 'print $.,":",$_ if /bla/' file alternatively sed: sed '/bla/!d;=' file |sed 'N;s/\n/:/'


2

Use this: c=132 for f in *; do mv -v "$f" "enum-$(printf '%0*d' 5 $c)" c=$(($c+1)) done The c=<your_starting_number>; I assumed 132 as in your question. Then the for loop runs trough all the files in the current directory. For every file the mv command is called. the printf utility prints the new filename with leading zeros. And finally the ...


3

uniq is the correct tool for that: uniq -D -f2 file Where: -D prints all dublicates -f2 to avoid to compare the first 2 fields Edit: If the fields 7 and above are not to be compared, you need awk: awk 'n=x[$3,$4,$5,$6]{print n"\n"$0;} {x[$3,$4,$5,$6]=$0;}' file The array item x[] (columns 3-6) is checked. If it's already set run the part in {...} ...


0

Does the problem go away if you run the function like this? irc_notify </dev/null & If so, the problem is probably two processes simultaneously trying to read from stdin. Running all ssh commands with -n, like zackse suggested, might also help, at least to debug which processes are fighting over stdin. (I'd post this as a comment because it's ...


1

Since /etc/rc.local is executed at the end of each multiuser runlevel, it's not the correct place to add start scripts. I recommend to not use /etc/rc.local in any way. It's a reclit for early *nix times. Instead of that, create a startup script in /etc/init.d/name which accepts start and stop arguments to start or stop the deamon, process or the job: #! ...


12

It's possible to use signals to communicate between the foreground and background shells: #!/bin/bash # global variable for foreground shell boolean=false # register a signal handler for SIGUSR1 trap handler USR1 # the handler sets the global variable handler() { boolean=true; } echo "before: $boolean" # Here, "$$" is the pid of the foreground shell { ...


8

The & character makes a background process. A background process is executed asynchronously in a subshell. Variables can be passed from a parent shell to sub shell, not the other way around. However, you can do a workaround if you are really in need of the value set in the child shell: boolean=$(mktemp) && echo "false" >$boolean { sleep 5 ...


4

You mistakenly assume that the boolean you set to true in the second line is the same boolean that you test for in the until statement. That is not the case, you start new process, with a new shell in the background and boolean (the one you test for), never gets assigned.


0

With zsh: print -rl mydir/**/*.A(.e_'REPLY=$REPLY:r; [[ -f $REPLY.B ]]'_) :r removes the extension, so if the content of $REPLY was mydir/somedir/somefile.A after running REPLY=$REPLY:r its content becomes mydir/somedir/somefile; the rest is similar to this answer.


2

Assuming: hour=09 Just use that: grep "\.$hour" file With the single quotes in your example, the variable is not interpreted as variable. Therefore the pattern searches for $hour. Also the dot has to be escaped, else it would match any character.


0

Your script repeats the print because awk is receiving two lines from egrep. But that has already been covered in other answers. I want to explain some alternative way to solve the problem, shorter, easier. The program cal could print the week starting on monday (which simplifies the math) when called as this cal -NMC month year. Using that: #!/bin/bash ...


1

The easiest way to do this is: $ for i in {1..3}; do cat inputfile$i>>outputfile; done


4

You can use '@', for example: $ files=( /tmp/a "/tmp/a file from windows" /tmp/myfile ) $ cat "${files[@]}" > newfile The '@' expands the entire contents of the array. It is similar to *except it will treat each element individuals whereas * will combine all elements as one.


0

This is trivial with zsh. % echo blah > a; echo asdf > b; echo harfjr > c; % filenames=(a b c d e) % print -l $filenames[1,3] a b c % cat $filenames[1,3] blah asdf harfjr % cat $filenames[1,3] > anewfile % cat anewfile blah asdf harfjr % somenum=2 % print -l $filenames[1,$somenum] a b % If the shell is actually bash or ksh uhhh dunno.


0

In addition to having a capital if as Scott pointed out, the terminal may require termination of the "then" statement (assuming you are pasting it in on one line). Try pasting: if [[ $(autorep -J jobname | cut -c108-110 | sed -n '/ST/!'p | sed '/^$/d' | sed -n '/_/!'p) == *ST* ]]; then echo "Status is Started"; fi (note the semi-colon before the fi)


0

Perl can do it, even across line breaks. Dump this into a file (I'll call it example.html): <p>Here is some <span>foo bar</span> example text.</p> <p>Some text even <span>foo bar</span> spans across line breaks.</p> Then try it out: $ perl -0777 -pe 's/<span.*?span>//gs' example.html <p>Here is ...


4

You indicate that you said If.  bash keywords are case-sensitive; you must use if (lower case).


0

sed 's/||$/&\n|-/;s/^||/|/;1s/^/{|\n/;$s/-$/}/' file Note \n is GNU sed only, thus should otherwise be sed 's/||$/||\ |-/;s/^||/|/;1s/^/{|\ /;$s/-$/}/' file


0

using sed sed 's/^[0-9]/chr&/' file


1

You are unlikely to find such a tool, as csh is widely viewed to be inappropriate for shell scripting. If you have any Bourne-derived shells available to you (e.g. sh, ksh, mksh, ash, dash, bash), you should consider reimplementing your work in one of those, or use a more complete scripting language such as Awk or Perl. You'll find far more robust tools for ...


0

As already mentioned in the comments by Fiximan, looking for a digit automatically filters out 'rs' and 'chr'. So if you want to prepend lines starting with a digit with 'chr' you can do the following: awk '{if ($1 ~ /^[:0-9:]/) printf "chr%s\n", $0; else printf "%s\n", $0;}' filename > newfile


0

The dig(1) or host(1) commands can be automated to lookup A records: % for d in example.com example.org; do dig +short A $d; done 93.184.216.34 93.184.216.34 % for d in example.com example.org; do host -t A $d; done example.com has address 93.184.216.34 example.org has address 93.184.216.34 % As a script, one way would be: $ cat domlu ...


1

Here is your code, expanded for viewability: awk ' { if (! ($1 ~ /rs/ || $1 ~ /chr/) ) { ($1 == "chr"$1); print $0} }; else { print $0 } ' filename > newfilename There are a number of issues with this that spring to mind You're using an equality comparison instead of assignment to ...



Top 50 recent answers are included