Tag Info

Hot answers tagged

22

Bash maintains the list of commands internally in memory while it's running. They are written into bash_history on exit: When an interactive shell exits, the last $HISTSIZE lines are copied from the history list to the file named by $HISTFILE If you want to force the command history to be written out, you can use the history -a command, which will: ...


15

Easy trick for alias in $(compgen -a); do type $alias; done


8

Very simple: for i in *; do echo "<$i>" done This uses bash's file globbing. A sort is not necessary as bash already sorts pathname expansions. From man bash: Pathname Expansion After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [. If one of these characters appears, then ...


8

The construction <(tac file) causes to shell to: Create a pipe with a name On systems such as Linux and SysV which have /dev/fd, a regular pipe is used, and /dev/fd/<the-file-descriptor-of-the-pipe> is used as the name. On other systems, a named pipe is used, which requires creating an actual file entry on disk. Launch the command tac file and ...


7

This is what Bash while loops do: while /path/to/application.app do : done It will run the application, and if it terminates successfully run the body of the loop. : is the shell's no-op command (the loop has to have a body, so that's what we put there); after that it goes back to the top and runs the program again. If it fails, the loop stops running ...


6

-o comm= means user output should be the command name only, but without any column title. E.g. if you do -o comm=COMMAND, it will print you a column title COMMAND: $ ps -o comm= -p $PPID xterm $ ps -o comm=COMMAND -p $PPID COMMAND xterm -p $PPID selects the process by the given parent's PID, the PPID. That means -o comm= -p $PPID are two independent ...


6

You can almost definitely just do: alias >>./bash_aliases


5

You could use the $? variable to get the return code of wget. If it's non-zero then it means an error occured and you tally it up until it reached a threshold, then it could break out of the loop. Something like this off the top of my head #!/bin/bash threshold=0 for x in {90..110}; do wget ...


5

If you're happy with a loop: for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg' do wget "$url" || break done That will run wget for each URL in your expansion until it fails, and then break out of the loop. If you want two failures in a row it gets a bit more complicated: for url in ...


5

An ugly way of doing this (i.e. causing a function call in shell based on output from awk) could look like this: awk -F '\t' ' FNR < 2 {next} FNR == NR { for (i=2; i <= NF; i++) { if (($i == 1) || ($i == 4)) printf "retrieve %s\n", $i if (($i == 2) || ($i == 2)) printf "retrieve2 ...


5

bash keeps it in working memory, bash can be configured to save it when bash closes or after each command, and to be loaded when bash starts or on request. If you configure to save after each command, then consider the implications of having multiple bash running at same time. (command lines will be interleaved)


5

You're basically wanting to reset the terminal color right before bash executes the command. This can be done with a trap. For example: trap '[[ -t 1 ]] && tput sgr0' DEBUG Bash executes the DEBUG trap immediately before the command, so this will result in tput sgr0 (which resets formatting attributes) being run before each command. The [[ -t 1 ...


4

while [ $X -lt "$1" ] is being evaluated even when there is no $1. Move the rest of the code into an else block so this doesn't happen. function random-word { # from linuxconfig.org if [ $# -eq 0 ] then echo "I need an argument, dummy" # To be extra friendly, give them a random word. echo "Here's a random word:" ...


4

A GNU awk solution that treats , or \n as a record separator and - as a field separator. An equality check or a range check is applied depending on number of fields awk -v num=348 -v RS=',|\n' -F'-' 'NF == 2 && $1 <= num && $2 >= num{c++}; NF == 1 && $0 == num{c++}; END{print c+0}' file 2


4

I assume that the string can contain any character except newlines and null bytes. You can quote the string for use as a sed pattern. The characters $*./[\^ need to be preceded by a backslash. In the replacement text, you need to quote the characters \&/. regexp=$(printf %s "$old" | sed 's:[$*./\[^]:\\&:g') replacement=$(printf %s "$new" | sed ...


4

There are many ways to do this, here are some: Use seq as @Gnouc suggested. Use brace expansion and convert spaces to commas: $ echo {5..1} | sed 's/ /,/g' 5,4,3,2,1 Use your script but change decrement the counter instead of incrementing it and change echo to echo -n (this will work for bash's builtin echo but not for all echo implementations): i=5 ...


4

In bash you can set nocaseglob: shopt -s nocaseglob for file in "$arg"/**/*.{txt,h,py} do .... done shopt -u nocaseglob noclaseglob is fine to use in any bash since 2.01, however ** requires bash or later (an it follows symlinks up to bash 4.3). Note the correction to quote $arg since there will be problems if this contains spaces or glob characters. ...


4

You're backgrounding the application, and the application is generating output. Your prompt is still there, it just has extra stuff being shown. For example: $ ( sleep 1 && echo hello ) & [1] 24764 $ █ And then after a 1 second delay, I get: $ ( sleep 1 && echo hello ) & [1] 24764 $ hello █ The echo is just writing output to ...


4

What is difference between | and <<()? There is a difference between them: | cause each command run in a separated subshell. <() run the command, which is substituted in background. For the next two question, we will do some strace: pipe: $ strace -fc bash -c 'tac /usr/share/dict/american-english | grep qwerty' $ time seconds ...


3

With seq, you can do: $ seq -s, 5 -1 1 5,4,3,2,1 And a perl solution can be portable: $ perl -e 'print join ",", reverse 1..5'


3

If you can use perl: $ perl -F',' -anle ' for (@F) { ($l,$h) = split "-"; $count++ if $l == 348 || ($l < 348 and $h >= 348); } END {print $count} ' file 2


3

Not sure what you mean. Possibly with GNU grep: grep -Ero '(\\x[[:xdigit:]]{2})+' . To match strings of the format \xNN (the 4 characters backslash, x and two hexadecimal digits)


2

Use process substitution with & redirection and exec: exec &> >(tee -a "$log_file") echo This will be logged to the file and to the screen $log_file will contain the output of the script and any subprocesses, and the output will also be printed to the screen. >(...) starts the process ... and returns a file representing its standard ...


2

Assuming each line of arguments.txt represents a separate argument, with bash 4 you can read arguments.txt into an array using mapfile (each line from the file goes in as an array element, in sequence) and then pass the array to the command mapfile -t <arguments.txt source test.sh "${MAPFILE[@]}" The advantage is that splitting on spaces embedded ...


2

This answer will provide the fields that contain the specified number, not just the lines, if you are after that level of detail (and if the ranges in your data might contain overlaps): awk -v num=348 -F, '{ for (i=1; i<=NF; i++) { if ($i == num || (split($i, a, /-/) == 2 && (a[1] <= num && num <= a[2]))) { print $i ...


2

Since you state that the file is sorted, shouldn't it be possible to use a simple loop with memory for only the preceding appId string? Kind of like @Qeole's sed approach but avoiding the overhead of regular expresssions by using the shell's delimited read function plus string comparison: #!/bin/bash appId="" while IFS=\; read -r s1 s2 s3 userId; do if ...


2

A sed answer: sed ': l;N;s/^\([^;]\+;[^;]\+;[^;:]\+\)[;:] *\(.*\)\n\1;\(.*\)/\1: \2, \3/;tl;P;D' input_file.txt File is read only once, so performance shouldn't be too bad, but I can't tell you more than that. With details: sed ': l; # Label l N; # Add next line of input to pattern space s/^\([^;]\+;[^;]\+;[^;:]\+\)[;:] ...


2

In Perl perl -F';' -lane 'push @{$h{join ";",@F[0..2]}},$F[3]; END{ for(sort keys %h){ print "$_: ". join ",",@{$h{$_}}; } }' your_file You should be able to do something similar in awk using associative arrays, but I'm not really that well-versed in awk ...


2

You don't need an else block. And you don't need to fail if you receive more than one argument. You only need to fail if you don't get an argument and you can then just ignore everything else or quit if you don't get at least the one. set -- "${1?ERR: Where\'s my argument?!?!}" That statement does all of that. This does the same but also fails if the ...


2

Use zsh instead: setopt extendedglob for f ($arg/**/*.(#i)(txt|h|py)(N.)) { ... } (the (N.) is to not return an error if there's no matching file and select regular files only (the equivalent of find's -type f))



Only top voted, non community-wiki answers of a minimum length are eligible