New answers tagged

0

Some great recommendations I have received so far are: gnuplot graphviz visidata (especially intuitive and powerful tool for exploring CSV files and more!)


1

if you use find , it's return full path : $ find /kafka/topics /kafka/topics/bgol.ase.fgt.dad3-1 /kafka/topics/bgol.ase.fgt.dad3-100 ... so , you should be add * after var and befor this var like that *$topic* , finallment find /kafka/topics -name "*$topic*" -exec rm -rf "{}" \;


0

You don't need to escape the double quotes in a here-doc. The way you have it there, the outer shell expands the variables, and the shell started by su sees -p \"gy75k9([0y6se2v^\" literally, the backslashes escape the quotes, and the ( is unquoted. Without the backslashes, it should work as long as the password doesn't contain \, $, " or ...


4

There are some flaws in this code. Don't parse ls. And since you have the command substitution quoted every result is passed to INV as a single string. Instead you can just loop over the glob results: for inv in np4178/*pdf; do You don't need any of the ;'s or \'s in that code. In fact the way they are written actually cancel each other out. ; is a ...


0

This method (slightly different than what has been posted so far) worked best for me echo "/dev/$(ps -p $$ -o tty=)" To use it for a parent process e.g., substitute $$ with $PPID.


1

#!bin/bash should be #!/bin/bash Otherwise it will assume a directory bin in the current path and looks there for bash.


0

The currently accepted answer does always step, once started and therefore also "skips" over breakpoints, signals and even the program end (in the last case raising a single error "The program is not being run" before gdb internally aborting the while where that happened). As an additional culprit it stops if pagination is on (which is ...


2

I'll simplify and call your exec line just "exec" and the prepending lines (with the exports) "pre1" and "pre2". You could "skip" two lines on /pre1/ by loading them in the hold space and do the "empty" command b: sed '/pre1/{N;N;b};/exec/ipre1\npre2' That way the command for /exec/ is only run when /pre1/ ...


0

The way to expand the *.txt in the current directory and count the number of names that matched is to do set -- ./*.txt This sets the positional parameters ($1, $2, etc.) to the names matching the globbing pattern. If the nullglob shell option is set in the bash shell, this would be an empty list if there are no matches, otherwise the list would contain ...


1

This modified script adds support for single numbers: #! /bin/bash civic="$1" street="$2" if [ "$((civic%2))" = 1 ]; then exclude=" even " else exclude=" odd " fi </path/to/addresses.txt grep -E "(^| )$street" \ | grep -v "$exclude" \ | awk -F '[ -]' -v civic="$civic&...


2

You seem to be mis-reading the assignment's question. it says "current directory", which is ., not ~ or ~/linux2/q3 it also says "and all subdirectories". Given that this appears to be an introductory shell-scripting course, it's extremely unlikely that they expect you to write your own code, in bash, to recurse subdirectories. That ...


3

There are several syntax errors in your code. The first one that is triggered is the missing ; in front of do in the for loop header. Fixing that yields while read num; do There is also a fi missing for the first if statement. Fixing this: if [ num -eq 0 ]; then zeroSum=$zeroSum+num elif [ num -eq 1 ]; then oneSum=$oneSum+num else ...


2

alias ls='\ls --color=auto --group-directories-first' No need for the backslash, the shell doesn't fall into such a trivial loop: The first word of the replacement text is tested for aliases, but a word that is identical to an alias being expanded is not expanded a second time. And then suppose I call a shell script of mine containing a function, e.g....


1

Your context is such that you want to execute a script in its environment rather than sourcing it in the calling shell. In that case there is no need to escape any command name in script, even though that name may be previously aliased. Aliases are not carried over to script environment without sourcing the file that contains their definitions. A script is ...


0

The question you are asking is how to use ++ to increment an array index. Like this: folderArray=( sdb sdc sdd sde sdf sdg ) counter=0 for i in disk1 disk2 disk3 disk4 disk5 disk6; do folder_name=${folderArray[counter++]} echo mkdir /data/$folder_name done The index of an array (what's inside the []) is in an Arithmetic environment, so the post ...


1

This type of splitting has nothing to do with IFS. It is the very basic kind of splitting that converts a line into words. Words are the individual tokens over which a shell could act. Like reading a sentence is done by dividing it into words first and then understanding what the words mean. The only way to avoid such splitting is by quoting. That is the ...


0

Turns out I incorrectly compiled ncurses, deleting the ncurses directory and then starting from their did the trick.


4

As stated by others in comment to your question, your script does not work because when the start condition [[ "$line" == "$2" ]] is met, extract is set to 1, but on the next line the end condition [[ "$line" == "$3" ]] is also met, which reset extract to the empty string. Here is your script fixed: # Usage: extract ...


0

Add a toggling logic to the extract variable whenever $2 is seen. Thanks to xhiene for pointing it out.! [[ $line == $2 ]] && case $extract in '') extract=1;; *) extract=; esac And remove the $3 dependency on extract variable now. HTH.


1

With awk and a bash wrapper. Save it as script.sh and make it executable. #!/bin/bash filename="data.txt" n="$1" # save number from argument list shift # remove number from argument list s="$@" # save remaining argument list s="${s:=.*}" # set regex .* as default if street is missing awk -v number=...


1

#! /bin/bash civic="$1" street="$2" if [ "$((civic%2))" = 1 ]; then exclude=" even " else exclude=" odd " fi </path/to/addresses.txt grep "$street" \ | grep -v "$exclude" \ | awk -F '[ -]' -v civic="$civic" ' {if ($1 !~ /^[0123456789]*$/ || $2 !~ /^[...


0

Many different ways to achieve this, but cut is likely the easiest. cut -f1 -d" " inputfile >column1.txt cut -f2 -d" " inputfile >column2.txt


2

Though sub-optimal, the following method works fine in a pinch: declare -A fundocs_; doc() { fundocs_[$1]=$2; } help_doc() { echo "$1: ${fundocs_[$1]}"; } doc hi_from_fun "Send a short greeting" hi_from_fun() { echo "Hi there"; } help_doc hi_from_fun will print documentation as follows: hi_from_fun: Send a short greeting ...


1

What you see is the intended behavior when you use the basic completion mechanism complete -W. If you want a more intelligent completion, you need to to write completion functions (see the "Programmable Completion" section in the Bash manual) and use complete -F. Here is how to adapt your example: $ comp_d() { COMPREPLY=( $( if [ "$...


0

Another example that I was just testing given your's is to create consecutive files in specific sub directory like I have it here. ├── FOLDER │   ├── FOLDER1 │   └── FOLDER2 ├── FOLDER │   ├── FOLDER1 │   └── FOLDER2 └── FOLDER ├── FOLDER1 └── FOLDER2 I used this command below to create in only the FOLDER2 dir files with consecutive number sequence ...


0

D-Bus checks whether UIDs of the calling process and the session daemon are the same. Your script needs to run notify-send as the target user. If you insist to run the script as root then in the script you need sudo -u user notify-send …. Keep in mind sudo sanitizes the environment, so DBUS_SESSION_BUS_ADDRESS from the environment of the script will not get ...


2

Functions are defined in the same way in an interactive bash shell as in a bash shell script. Taking your example as a starting point: my_func () { do_stuff "$1" "$2"; } You would type that on the command line. Then call that (also on the command line) with my_func 'something' 'something else' 'a third thing' Note that you don't declare ...


0

I wrote a bash function called MAGIC that takes n space separated lists and converts them into a set of SQL values, thus retaining most of your original syntax. it uses standard SQL escaping which so far as I can tell is the syntax expected by Sqlite. It will work for any number of columns greater than zero. # MAGIC a variadic function. # named for a ...


3

Let’s split it up: [ "$foo_user" = 'foo' ] checks whether the foo_user variable’s value is “foo”. && foo_user='bar' runs if the previous command succeeded (&&); thus if foo_user’s value is “foo”, it is set to “bar” instead. || true runs if the previous command failed (||); thus, in all cases, the compound command (in this case, ...


1

~ as stand-alone - that is unquoted - is interpreted by the shell as being the home directory. When you quote it, that interpretation stops, so it is not like ordinary variables. . and .. are references in the file system. So, if you try to use . in a C program (so without the shell) that would work, as in: #include <stdio.h> int main(void) { DIR *d;...


4

The dot . isn't a special character in the shell. All the properties of the . and .. directory links are just about the filesystem structure, the shell has nothing to do with it. Note that even there, it's not the character, but those two specific names. foo.txt, .bar and ... are regular file names, even if the ones starting with a dot are treated specially ...


0

For me it worked out with the following: dpkg-query -l | awk '{print $2 " Version Number " $3}'


1

A program (script, application, whatever) does not get to see the command line that invoked it. It gets given a series of zero of more parameters parsed by the invoking shell. For example, when you run ls f* it's not ls that handles the f*, it's the shell. If you had three files beginning with f, then ls f* might be parsed by the shell to become ls final ...


-1

Remove all instances of /bin/bash in your crontab jobs; replace it with a single SHELL=/bin/bash in the crontab. cron's default shell is /bin/sh. bin/sh does not support use of the ~ abbreviation for the user home directory, and using it here could lead to "bad habits". Consider replacing all instances of ~ with the full path; e.g. /home/theuser/....


0

I would use a temporary file to store the complex function result, and then read the value from the temp file for processing. # Create a temp file for storage tmppath=$(mktemp) # run the command and get the output to the temp file complex_command > ${tmppath} # read the file into variable message=$(cat "${tmppath}") # use the variable echo "...


0

You can do with a sed-grep pipeline: $ sed -e 's/$/x/' file1 | grep -xFf - file2 c,3,val3x e,5,val5x Notes:- First prepare the file1 data for being searched against data in file2 -x => full line match and not a partial match -F => is for string match and not regex match -f => file contains strings to be looked for


1

The command you typed was parsed by your current shell before the shell even attempted to run watch. The shell interpreted ; and do because you did nothing to protect these from the shell. do was unexpected, but in the first place you did not want the shell to interpret ; as a command terminator. In general you protect things from being interpreted/expanded ...


5

watch's command argument(s) are a script that is run with sh -c. If the command arguments are just a list of tokens separated by spaces (e.g. watch ls -l), it concatenates them all and runs them. But unquoted shell meta-characters are used by the shell that you run watch from and are never seen by watch. This means that meta-characters like ; & | < &...


1

How about awk? $ awk -F, 'NR==FNR{a[$1,$2]=$3; next} ($1,$2) in a && $3 != a[$1,$2]' file1 file2 c,3,val3x e,5,val5x If you need to handle advanced CSV features (in particular, embedded commas in quoted CSV fields, which a simple awk -F, won't deal with) then there's always the Python-based csvkit suite of tools. In particular you could use csvsql: $...


0

Another way to accomplish. Suppose that you have some file foo.sh that you want exclude from your operation, yet you want to add csv to every other file. You could use the following loop: for f in *; do if [ "${f: -3}" != ".sh" ]; then mv "$f" "${f%}.csv" fi done


0

Try: parallel echo "IS_${ACQ}_tr{3}_{1}_{2}.h5" ::: "${ANGLES[@]}" ::: "${VAR[@]}" ::: "${TRAIN[@]}"


2

You never have to calculate the number of rows needed. You just need to make sure that you insert newlines after every $cols number. Using seq and awk: $ num=28 $ cols=6 $ seq "$num" | awk -v cols="$cols" '{ printf "%-4d", $1 } NR % cols == 0 { printf "\n" } END { printf "\n" }' 1 2 3 4 5 6 7 8 ...


4

You have FILE= (singular) and for f in $FILES (plural). Beyond that though, look at the difference in the output of the 2 echo statements below: $ ls tmp File-0 File-1 File-2 File-3 $ files=tmp/File* $ echo "$files" tmp/File* $ files=( tmp/File* ) $ echo "${files[@]}" tmp/File-0 tmp/File-1 tmp/File-2 tmp/File-3 You COULD get a list ...


1

Depending on your exact use-case, zgrep may do the trick: zgrep ... /var/log/dpkg.log* | grep installed (Note that the three dots ... are required)


0

You can pipe the output to dpkg -s: comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz \| sed -n 's/^Package: //p' | sort -u) | xargs -n1 dpkg -s |grep 'Package:\|Version:'


3

The sqlite3 command-line tool does not support prepared statements, so any attempt to do this in a shell script is going to run into problems with un-escaped quotes and the like. Dealing with quoted and unquoted variables is already a bit of a pain in shell/bash, and that pain only gets worse when you're working with an SQL database which has its own ...


3

Replace the first set of export lines with this export PATH="$PATH:$HOME/.local/bin:$HOME/bin" [[ -d "$HOME/bin/prog1" ]] && PATH="$PATH:$HOME/bin/prog1" [[ -d "$HOME/bin/prog2" ]] && PATH="$PATH:$HOME/bin/prog2" [[ -d "$HOME/prog2" ]] && PATH="$PATH:$HOME/prog2" [[ ...


6

. .bashrc would run the contents of .bashrc in the current shell. Usually, you don't need to do that, since .bashrc is read by the shell when it starts, but if you make modifications to it and want to reload them, you might do that. But doing that in one interactive shell shouldn't affect other shells you start on later logins. What you have there in ....


2

Here's a bash script that will do the <MAGIC> you want #!/bin/bash # FNAMES="John Paul George Ringo Andrew Nicci" LNAMES="Lennon McCartney Harrison Starr O'Brien Müller" # Convert strings to space-separated arrays (lists) # Bad things will happen if you have names with spaces (e.g. "Sarah" + "Maddison Smith") ...


1

Adding a fake root node around your broken XML is easy enough, modifying the modified XML would be a breeze with xmlstarlet, and deleting the added root node (and the <?xml version="1.0"?> that xmlstarlet adds) once you've modified it is not too hard either: { echo '<root>'; cat file.xml; echo '</root>'; } | xmlstarlet ed -u '//...


Top 50 recent answers are included