Tag Info

New answers tagged

2

The answer is here: status="0" pidofproc $pidfile $daemon >/dev/null || status="$?" So status_of_proc calls pidofproc which sets $base. This variable value is set in the current shell and so its value persists when pidofproc returns to status_of_proc. For example: fn1() { unset var; fn2; echo "$var"; } fn2() { var=set; } fn1 OUTPUT set In the ...


0

Consider Enabling Portage ELogging. Taken from the Gentoo Wiki: Portage Log. Inside /etc/portage/make.conf: Set PORT_LOGDIR, i.e. PORT_LOGDIR="/var/log/portage" Set PORTAGE_ELOG_CLASSES, i.e. PORTAGE_ELOG_CLASSES="log warn error" Set PORTAGE_ELOG_SYSTEM, i.e. PORTAGE_ELOG_SYSTEM="save" You can also set Option 3 differently depending on your ...


1

There are no built-in function to colourize logs, but there's Vim with its messages highlighter that makes logs easier to read and also highlights lines with certain keywords ("error", "failed", etc.) in red. Try :setf messages. ccze - A robust log colorizer — a replacement for colorize that apparently has lots of ways to customize it colourization ...


1

I'm not sure what are you trying to achieve, but if your function will somehow interact with portage then perhaps you could use its color definition. From man 5 color.map: VARIABLES NORMAL = "normal" Defines color used for some words occuring in other contexts than those below. BAD = "red" ...


0

if mount | grep -q "/mnt/mountpoint" ; then echo "mounted" fi or for nfs if mount | grep -q "/mnt/mountpoint" | grep -q nfs ; then echo "mounted" fi


2

$1 is the first argument to the script, i.e. list.txt LIST=$1 simply copies that filename to the LIST variable, so $LIST now contains lists.txt as well -- it doesn't contain 12345. while read PDF do ... done < ${LIST} starts a loop whose standard input is redirected to the file list.txt, and each time through the loop it reads a line from the ...


0

I would do like... #!/bin/sh -x run() if ! ps -p "$run" >&2 then n=0 run=$$ exec "$0" "$@" 2>&1 | { ! tee outfile ; } fi 2>/dev/null run "$@" || exit fn() { var=val$n; echo "$((n+=1)): $var"; } fn sleep 5 fn IN That first checks if it's already got an open pipe to a tee in another process, and, if not, it execs ...


2

You can do something like: func > >(tee log.txt) 2>&1 wait You can dedicate a file descriptor for logging: exec 3> >(tee log.txt) tee_pid=$! func >&3 2>&1 ... Beware though that as that tee runs in background, if not all the output goes through it, then the order in the output may be affected.


0

You can use a tmp file func >tmpfile 2>&1 tee 'log.txt' <tmpfile or a FIFO mkfifo pipe_replacement tee 'log.txt' <pipe_replacement & func >pipe_replacement 2>&1


0

You might do: TMPDIR=${TMPDIR:-${TMP:-$(CDPATH=/var:/; cd -P -- tmp)}} cd -- "${TMPDIR:?NO TEMP DIRECTORY FOUND!}" The shell should either find one of the 4 alternatives or exit with error. Still, POSIX defines the $TMPDIR variable (for XCU systems): TMPDIR This variable shall represent a pathname of a directory made available for programs that need ...


5

If you're looking for the same thing in fewer lines... for TMPDIR in "$TMPDIR" "$TMP" /var/tmp /tmp do test -d "$TMPDIR" && break done You could write this in one.


12

A slightly more portable way to handle temporary files is to use mktemp. It'll create temporary files and return their paths for you. For instance: $ mktemp /tmp/tmp.zVNygt4o7P $ ls /tmp/tmp.zVNygt4o7P /tmp/tmp.zVNygt4o7P You could use it in a script quite easily: tmpfile=$(mktemp) echo "Some temp. data..." > $tmpfile rm $tmpfile Reading the man ...


0

In echo -e "? \c", the \c part is not anything that gets printed out, it's a directive to the echo command to not print a newline after the string passed as an argument¹. So in expect, you need to expect the string "? " (question mark, space). Since the argument of the expect command is a pattern where ? is a wildcard, you need to interpret the question mark ...


2

As goldilocks’ comment and humanity’s references describe, shift reassigns the positional parameters ($1, $2, etc.) so that $1 takes on the old value of $2, $2 takes on the value of $3, etc.*  The old value of $1 is discarded.  ($0 is not changed.)  Some reasons for doing this include: It lets you access the tenth argument (if there is one) more easily.  ...


0

You're almost there. Consider using the read built in (From TDLP: Catching User Input): Read Example cat leaptest.sh #!/bin/bash # This script will test if you have given a leap year or not. echo "Type the year that you want to check (4 digits), followed by [ENTER]:" read year if (( ("$year" % 400) == "0" )) || (( ("$year" % 4 == "0") && ...


0

The next awk statement will skip the current line, that is useful if you have to match multiple blocks in your script. awk ' /^#/ {next} / pattern 1 / { } / pattern 2 / { } ' filename


1

Using grep: grep -vE "^#" or grep -E "^[^#]"


-1

sed 's/#.*//' This gets rid of comments, even if they don't start at the first column.


1

awk -F: '/^[^#]/ { print $2 }' /etc/oratab | uniq


1

SCRIPT_1="ksh -x script1.sh & bg_pid=$!; ksh -x script2.sh; wait $bg_pid"; SCRIPT_2="ksh -x script3.sh & bg_pid=$!; ksh -x script4.sh; wait $bg_pid"; eval $SCRIPT_1; sleep 20s; eval $SCRIPT_2;


1

> awk '/^[^ ]/ {printf "\n%s",$1; next}; { printf ",%s",$3; }' file 360060e80056fc30000006fc30000513c,sdcm,sdcn 360060e80056fc30000006fc300005162,sdbu,sdbv 360060e80056fc30000006fc300005127,sdg,sdt


2

Use an array since that can expand to a variable number of arguments: #!/bin/bash # This is file caller.bash switch=() if [[ ${1-x} == x ]] then switch=("--abc=long argument") fi some_command.sh "--exclude=*~" "${switch[@]}" arg Or you could use the ${var+...} syntax: #!/bin/sh # This is file caller.sh unset switch if [ "${1-x}" = x ] then ...


1

dirname="${var1}${var2}" mkdir -p -- "$dirname"


1

Here's a variant on Cyrus's answer that uses parameter indirection. However, as the link says, array-based approaches are to be preferred over the use of indirection, as such indirection is a close cousin of eval, which should be avoided whenever possible. (I've reduced the ranges of the numbers from those given in the OP just to make the output a bit ...


5

Depending on the version of sed on your system you may be able to do sed -i 's/Some/any/; s/item/stuff/' file You don't need the g after the final slash in the s command here, since you're only doing one replacement per line. Alternatively: sed -i -e 's/Some/any/' -e 's/item/stuff/' file The -i option tells sed to edit files in place; if there are ...


6

You can chain sed expressions together with ";" %sed -i 's/Some/any/g;s/item/stuff/g' file1 %cat file1 anything 123 stuff1 anything 456 stuff2 anything 768 stuff3 anything 353 stuff4


5

Multiple expression using multiple -e options: sed -i.bk -e 's/Some/any/g' -e 's/item/stuff/g' file or you can use just one: sed -i.bk -e 's/Some/any/g;s/item/stuff/g' file You should give an extension for backup file, since when some implementation of sed, like OSX sed does not work with empty extension (You must use sed -i '' to override the original ...


0

I don't think diff (even in combination with cut) will be flexible enough to handle this. And it seems as though what you really want is keys in file1 that are not in file2 and vice versa - not strictly a line-by-line diff. If the input files are big, I would go with perl, but for small files this awk script works for the input provided: %cat a.awk BEGIN ...


3

awk is a better tool for comparing columns of files. See, for example, the answer to: compare two columns of different files and print if it matches -- there are similar answers out there for printing lines for matching columns. Since you want to print lines that don't match, we can create an awk command that prints the lines in file2 for which column 2 has ...


0

You need eval to do it the way you're trying to do... numbers2004={625..721} numbers2005={723..823} for year in 2004 2005 do eval 'eval "for number in '"\$numbers$year"' do echo \"\$year \$number\" done"' done ...which prints... 2004 625 ... 2004 721 2005 723 ... 2005 823 But that is kind of a horrible way to do it - and not only because the ...


0

You can also achieve this with variable indirection: #!/bin/bash numbers2004="$(printf "%s " {625..721})" numbers2005="$(printf "%s " {723..823})" for year in 2004 2005 do for number in $(eval echo \$numbers$year) do echo "$year $number" done done


2

With current bash version: #!/bin/bash declare -A numbers # declare associative array printf -v numbers[2004] "%s " {625..721} printf -v numbers[2005] "%s " {723..823} for year in 2004 2005 do for number in ${numbers[$year]} do echo "$year $number" done done


5

shift is a bash built-in which kind of rotates the arguments. Given that the arguments provided to the script are 3 available in $1, $2, $3, then a call to shift will make $2 the new $1. a shift 2 will shift by two makeing new $1 the old $3. for more info see here http://ss64.com/bash/shift.html http://ss64.com/bash/shift.html ...


2

This command exits the chrome process tree gracefully, in all window managers: pkill --oldest chrome or if you prefer: /usr/bin/pkill --oldest --signal TERM -f chrome Details: gracefully means: avoid seeing “Google Chrome didn't shut down correctly. To repoen ...” next time chrome starts chrome browser (e.g. version 39.0.2171.95) traps and ...


1

Let's use AWK! This function lists the frequency of each word occurring in the provided file in Descending order: function wordfrequency() { awk ' BEGIN { FS="[^a-zA-Z]+" } { for (i=1; i<=NF; i++) { word = tolower($i) words[word]++ } } END { for (w in words) ...


4

You're mixing character classes (a list of characters inside square brackets) with the smb.conf share names which are surrounded by square bracket literals. Also, the echo command is not well-formed: in the case where sed exits with a non-zero status, the shell will attempt to invoke the command Failed. A few suggestions: Remove the character class (outer ...


-1

echo "enter first no :"; read a echo "enter second no :"; read b echo "sum = `expr $a + $b`"


3

Each part of pipelines run in separated processes, or own subshell. So when your pipelines finished, your current shell does not know anything about function f. With bash (ksh, pdksh, zsh, mksh or shell that support Here-String), your can use: $ source /dev/stdin <<<'f() { echo a; }' $ f a POSIXly, you should use Here-Document and dot: $ . ...


1

You can use process substitution source /dev/stdin < <(echo -ne 'f() { echo a; }\n') or source <(echo -ne 'f() { echo a; }\n') This works in bash 4.1.5, for some reason it doesn't work in 3.2.48.


2

The commands in a pipe are separate processes, hence the function definition that is sourced from /dev/stdin is lost as soon as the pipe completes. That is why the pipe show different results to the usage of the temporary file. In your use case the eval as suggested by PM 2Ring would be the way to go.


4

This script will not run correctly at boot time as gnome-terminal, firefox and gedit will expect a X session to be running. The init.d and/or systemd route is too early in the boot process for your requirements. You'd be better off creating a .desktop file and configuring your system to auto-start this on login. Create a the file as follows:- $ gedit ...


0

For the sake of comprehensibility and visibility I abuse an answer for explaining the quoting part. May the SE karma forgive me... This is (depending on the content of f) a special case, the problem is not easy to see: > f=foo > set -x > echo "reading entry: "$f"" + echo 'reading entry: foo' reading entry: foo The shells debug modus shows just ...


0

xmessage is obsolete and no longer maintained: it does not support UTF-8, etc. You should you gxmessage instead (xmessage clone based on GTK+).


1

Use file matching operator in your for loop. for f in *_*.png will match all the png file names as you specified and assign each name to variable f. Then inside the loop use the ${f%_*} bash operation to extract only the number of the file. FOLDER="$HOME/Images/Shutter" cd "$FOLDER" for f in *_*.png do num=${f%_*} shutter -f -e -n -o ...


3

There's no need to use sed, this can be handled by parameter expansion mv -- "$x" "${x//%20/ }" FWIW, I'd be replacing those %20s with an underscore (or something); I hate file names that contain spaces. But I guess learning how to write bash scripts that can handle spaces and other special characters in file names is a Good Thing. :) As Izkata mentions ...


5

Use rename and replace the %20 with a space in all type of files: $ rename -n 's/%20/ /g' * File%20with%20in00.yA2 renamed as File with in00.yA2 File%20with%20in01.h9H renamed as File with in01.h9H File%20with%20in02.CNR renamed as File with in02.CNR File%20with%20in03.PuP renamed as File with in03.PuP File%20with%20in04.js8 renamed as File with in04.js8 ...


6

Since the output of the mv probably will have spaces you need to put double quotes around the result in order not to try and execute commands in the for loop like: mv abc%20def abc def where mv has too many arguments. These are the ones giving you the usage: message. What you should do is: for x in *_MG*.CR2 do mv -- "$x" "$(printf '%s\n' "$x" | sed ...


2

You can figure out the amount of packets received and transmitted across eth0 by running the following commands: cat /sys/class/net/eth0/statistics/rx_packets cat /sys/class/net/eth0/statistics/tx_packets You could then use this fact to write simple a shell script which will poll these files every second, and then calculate and output a PPS value (packets ...


7

rm [0-9][0-9].* will do it for files in the current directory (no quotes — you want to match files). The . doesn't need to be escaped, because this is a shell glob and not a regular expression (if it were a regex, that would be a wildcard). If you are looking to do this recursively, find is probably your best bet.


5

Recursively : find . -type f -name '[0-9][0-9].*' -delete require GNU find, or : find . -type f -name '[0-9][0-9].*' -exec rm {} \;



Top 50 recent answers are included