Tag Info

New answers tagged

0

Joining the choir, you can also use awk to blank out the columns you don't want: [jis@localhost ~]$ ls -lh | awk '{$1=$2=$3=$4="";print}' 4.0K Aug 19 2014 Desktop 4.0K Jan 8 22:39 dir1 4.0K Feb 5 20:41 Documents 12K May 22 19:31 Downloads 4.0K Aug 19 2014 Music 4.0K May 3 20:00 Pictures 4.0K Aug 19 2014 Public 115K May 9 ...


5

Pass the -o and -g options to omit the user and group columns. Since user and group names can contain spaces, you can't reliably edit them out. There's no option to omit the permissions and link count columns. Since the first column you want to keep can start with whitespace (for right alignment), you can't use the whitespace-to-non-whitespace transition as ...


1

This works for me: ls -lhn | sed -r 's#^\S+(\s+\S+){3}##'


0

A nifty solution using grep: ls -lhn | grep -oP "^([[:graph:]]+\s){4}\K.+" Here, [[:graph:]] ==> all printed characters (i.e. no spaces, newlines) \s ==> space {4} ==> exactly four matches


0

If you want to copy all the .txt files in a directory, use a wildcard pattern: cp direct/direct1/*.txt target This copies all the .txt files that are in the directory direct/direct1 to the directory target (which must already exist). You can pass multiple patterns to copy files from multiple directories: cp direct/direct1/*.txt direct/direct2/*.txt ...


1

awk awk 'FNR==NR { a[$2, $3]=$4 next } ($2, $3) in a{ print $0, a[$2, $3] } ' file2.txt file1.txt > out.txt join join -j 2 \ <(sort -k2,3 file2.txt | sed 's/ /+/2') \ <(sort -k2,3 file1.txt | sed 's/ /+/2') \ -o ...


1

In your example you are creating array m with values 0. You nowhere set it to 1, and you don't need to. You can just set value to entire row, e.g $0. Try this: awk 'FILENAME == ARGV[1] { m[$2,$3] = $0; next; } { if (($2,$3) in m) { print m[$2,$3] " " $4 >"out.txt"; } }' file1.txt file2.txt


2

You can use find to only select the `.txt files from under some directory: find direct/direct? -name "*.txt" this would print out all the files, so you can check you got what you wanted, and not too much is going to be selected. The *.txt has to be quoted, otherwise the shell will try expand this to .txt files in the current directory. As for the ...


0

With Perl and bash: decoded=$( perl -lpe 'y/+/ /; s/%([0-9a-f]{2})/chr(hex $1)/egio' <<<"$str" )


7

From the manual (man bash): $(command)  or  `command` Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) ...


1

It's a lot of personal preference. Using a backtick to signify a command would be more POSIX compatible with older systems. The $() is more modern and is easier to read for some people. I would personally never use file_list_1=$(echo "list.txt"). It seems to ugly and has no additional use.


6

The nullglob option (which BTW is a zsh invention, only added years later to bash (2.0)) would not be ideal in a number of cases. And ls is a good example: ls *.txt Or its more correct equivalent: ls -- *.txt With nullglob on would run ls with no argument which is treated as ls -- . (list the current directory) if no files match, which is probably ...


3

From the wikipedia's "Checksum" article: A checksum or hash sum is a small-size datum from a block of digital data for the purpose of detecting errors which may have been introduced during its transmission or storage. It is usually applied to an installation file after it is received from the download server. By themselves checksums are often used to ...


4

#!/bin/sh - urldecode() { python -c "import sys, urllib as ul;print ul.unquote_plus(sys.argv[1])" "$1" } str="this+is+%2F+%2B+%2C+.+url+%23%24coded" decoded=$(urldecode "$str"} printf '%s\n' "$decoded" That is: avoid aliases in scripts as that's not guaranteed to work (some sh implementations like bash ignore aliases when non-interactive) quote your ...


3

With zsh, you could do: mkdir -p ~/.zsh/dirhist And add to your ~/.zshrc: HISTSIZE=1000 SAVEHIST=10000 setopt HIST_SAVE_NO_DUPS INC_APPEND_HISTORY HISTFILE=~/.zsh/dirhist/${PWD//\//@} chpwd() { [[ $PWD = $OLDPWD ]] || fc -Pp ~/.zsh/dirhist/${PWD//\//@} } chpwd() is called whenever the current directory changes. There, we reset the history file to ...


0

Isn't there some way to protect spaces in backtick (or $(...)) expansion? No, there isn't. Why is that? Bash has no way of knowing what should be protected and what shouldn't. There are no arrays in the unix file/pipe. It's just a byte stream. The command inside the `` or $() outputs a stream, which bash swallows and treats as a single string. As ...


8

Not a neat answer but an alternative if you're using bash as your shell: you could createt some alias in your .bashrc. For instance: alias a='cd /tmp/A ; history -w ; history -c ; export HISTFILE=/home/user/.a_history ; history -r $HISTFILE' alias b='cd /tmp/B ; history -w ; history -c ; export HISTFILE=/home/user/.b_history ; history -r $HISTFILE' Then, ...


1

This is entirely an issue with the command not being in your PATH. Unlike Windows systems the current directory is not implicitly in the search path for executables. To run a command such as ls (eg ls -l) it needs to be in your PATH, and indeed it is - type ls will show you it's either in /bin or /usr/bin. However, some.cmd is not in your PATH and so cannot ...


3

Capturing exit status of commands The assignment of command output to the rep variable does not lose the exit status of the curl command; it is still available as $?. For more details, see How can I store the return value and/or output of a command in a variable?. Curl exit code for failed HTTP requests Usually if a requested HTTP resource isn’t ...


4

The terminator is \$fff I'm going to assume that that's what @rici meant to say.  As his penultimate paragraph says, word does undergo quote removal, so \\$fff is dequoted to \$fff. But, as the man page says, no variable expansion is done so it stays that way.


5

If your script expects one prompt answered, or several prompts in which you can give the same answer, there's yes: NAME yes - output a string repeatedly until killed SYNOPSIS yes [STRING]... yes OPTION DESCRIPTION Repeatedly output a line with all specified STRING(s), or `y'. Use it like this: yes Me | give_a_hug.sh


9

The line which ends the here document is \$fff From the man bash section on Here Documents: The format of here-documents is: <<[-]word here-document delimiter No parameter and variable expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any ...


12

Expect can do that. From the Expect website: Expect is a tool for automating interactive applications such as telnet, ftp, passwd, fsck, rlogin, tip, etc. Expect really makes this stuff trivial. Expect is also useful for testing these same applications [...]" It comes with a lot of help, like autoexpect. Again from the Expect website, autoexpect ...


13

If the command is not very picky it should work with something like this: command > /dev/null << EOF <answer 1> <answer 2> <answer 3> EOF This requires that you know the exact answers beforehand.


0

Ugly as hell, but works: function foo echo bar; end setenv funcdefs (functions -n | perl -pe 's/,/\n/g' | while read d; functions $d; end|perl -pe 's/\n/\001/') perl -e '$ENV{"funcdefs"}=~s/\001/\n/g;system ("fish", "-c", $ENV{funcdefs}."foo")'


2

Any time you open a file (or anything that you can open like a file, like a socket) you get a file descriptor, which is represented by an int. The first 3 are automatically created for a process as stdin, stdout and stderr. Any other files that are opened get other descriptors. I suspect that it just increments the number each time, but I don't know if ...


2

If you so like awk awk ' FILENAME != ARGV[3] { m[$2,$3] = 1 next } !(($2,$3) in m) ' file3.txt file2.txt file1.txt > out.txt As for me much easy cut -d" " -f 2,3 file2.txt file3.txt | grep -v -f - file1.txt > out.txt


1

Possible solution with awk: awk 'FILENAME == ARGV[1] { m[$2,$3] = $0; next; } FILENAME == ARGV[2] { if (!(($2,$3) in m)) { m[$2,$3] = $0; } next; } { if (!(($2,$3) in m)) { print $0 >"out.txt"; } }' file3.txt file2.txt file1.txt First we read the first file and create array with keys column 2 and 3. Then we ...


2

In fish, you can use funcsave to save function definition across fish session: $ function qwerty echo qwerty end $ funcsave qwerty $ fish -c qwerty qwerty $ perl -e 'system "fish -c qwerty"' qwerty


2

These are effectively multi-line records separated by a blank line. Awk is great for handling this kind of data: pactl list sink-inputs | awk -v RS="" '/VLC/' If you want to be really nit-picky about not including the bottom part of the record after the first occurrence of "VLC", then: pactl list sink-inputs | awk -v RS="" -v FS="\n" '/VLC/{ for(i=1; ...


1

It’s remarkable how rarely cat is useful in a shell script.  $(cat source.txt | wc -l) is a classic useless use of cat; if you needed to count the lines in a file, $(wc -l < source.txt) is a much cleaner ways of doing it. But you don’t need to count the lines in source.txt. file=$(cat source.txt) is an ugly way to read a file; while read … do   ︙ done ...


1

I don't understand how the %\.* is removing the file extension That's because it doesn't. :) The code as written is wrong, and it doesn't accomplish anything useful. There is a standard shell expansion ${variable%pattern}, which takes $variable, and removes the shortest chunk at the end of it that matches pattern (there is a similar expansion ...


4

[ $i = "*f*" ] splits the file name stored in the variable i into separate words at spaces, interprets each word as a wildcard pattern and expands it if it matches, and then parses the resulting list of words as a condition for [ … ]. To avoid this rigmarole and instead use the file name, put double quotes around the variable expansion. [ "$i" = "*f*" ] ...


0

You don't need anything half as complicated as what you've written. You could just do: #!/usr/bin/env bash checksum="md5(" ## Read each line into the fields array (read -a fields), with fields ## separated by commas (IFS=,) while IFS=, read -a fields do ## If the 2nd element of the array is not "DATE" if [ ${fields[1]} != "DATE" ] then ...


3

The problem lies in how you're calling the . special builtin: exec /bin/sh -c '. vars.sh; /usr/bin/fish' In sh, if the argument doesn't contain any /, . searches for the file in $PATH. So above, it would look for vars.sh in $PATH instead of the current directory as you intended. Also, . being a special builtin, its failure causes the shell to exit (when ...


3

The quick answer is checksum="${checksum% || })" instead of checksum+=")". Just unconditionally add the || string in each step and then strip off the last unnecessary one at the very end (so the line_number computation is no longer needed). A better way to do this is awk -F, 'BEGIN { printf "md5( " } toupper($2) != "DATE" { printf "%s%s", sep, ...


5

With ed: ed -s <<'IN' r !pactl list sink-inputs /VLC/+,$d ?Sink Input?,.p q IN It reads the command output into the text buffer, deletes everything after the first line matching VLC and then prints from the previous line matching Sink Input up to current line. With sed: pactl list sink-inputs | sed -n 'H;/Sink Input/h;/VLC/{x;p;q}' It appends ...


5

I'd use Perl's paragraph mode: pactl list sink-inputs | perl -00ne 'print if s/(.*?VLC.*?\n).*/$1/ms' The -00 sets the input record separator to \n\n so a "line" is a paragraph. Then, the substitution will match everything until the first VLC and then anything until the 1st newline and save them as $1. Everything after that is removed (since we're ...


0

The other answers here were fine but were insufficient for my needs. I needed a solution that I could use in my scripts on any machine. My solution was to write a shell script which I can invoke from the scripts where I need it. #!/bin/sh if [ $# -eq 0 ] || [ $# -gt 2 ]; then printf 'Usage: respath path [working-directory]\n' >&2 exit 1 fi ...


1

Personally, I would go for a different approach. Presumably, you need the file in bourne-type format for other reasons. Why not just source it in fish by changing the format on the fly? Something like: source (grep = file | sed -r 's/(.+)=(.+)/set \1 \2/'|psub) The above is the fish equivalent of source <(grep = file | sed -r 's/(.+)=(.+)/set \1 \2/') ...


1

#!/bin/bash ss=0 for file do cp -fp -- "$file" "${file%.*}_copy.${file##*.}" || ss=$? done exit $ss This fails if file does not have a dot extension part. If you need that to work use Stéphane Chazelas's solution.


1

Since the OP is asking for a bash solution. Here is one that does. #!/bin/bash if [[ ! -f $1 && $(($# != 1)) ]]; then printf '%s\n' "Provide a filename" exit 1 fi inFile="$1" fileExt="${1#*.}" destFile="${1%.*}" cp -- "$inFile" "${destFile}_copy.$fileExt" # As suggested, so the files that start with a dash are not ignored.


-1

cp /example/directory/file.doc /example/directory/file_copy.doc this specifies the file name and will do what you want


4

No need for bash here, any standard sh interpreter implementation will do: #! /bin/sh - ret=0 for file do dir=$(dirname -- "$file") case $dir in (*[!/]*) dir=$dir/ # handle / and // specially esac base=$(basename -- "$file") name=${base%.*} name=${name:-$base} # don't consider .bashrc the extension in /foo/.bashrc ext=${base#"$name"} ...


1

Is this an exercise in iterations? If not the use of find may be easier search=$(find /path/to/dir -type f -name *f*) echo $search


1

The test ([ is synonym for the "test" builtin) command didn't allow patterns. STRING1 = STRING2 True if the strings are equal. so it compare strings letter by letter and sure there is not file with *f* name in your directory (so with your reverse-matching script echoes yes when names didn't match). Instead of test-buitin or even ...


1

Since you want to show only files that contain f letter in them, you'd need the continue builtin. For example for f in *; do if [[ $f != *f* ]]; then continue; else printf '%s\n' "$f yes"; fi; done In case you want to show all files with their corresponding yes or no you'd do something like: for f in *; do if [[ $f = *f* ]]; then printf '%s\n' "$f yes"; ...


0

While Ubuntu's default AltF2 is pretty useful, I've noticed in the comments that it does not work for you. An alternative run dialog that you can use is bbrun. This run dialog is originally for black box desktop environment, but can still be used elsewhere. Install it using sudo apt-get install bbrun. Once you do, run it in terminal with nohup bbrun & ...


1

Try pressing Alt+F2. I'm not totally sure about this though, as when I search Alt+F2 in LXDE on Google there seem to be a fair number of results about a bug. Not sure if those still apply. However, this is the shortcut that worked for me last time I used LXDE.


1

Awk could do this easily if the output was in decimal, but it can't parse hexadecimal numbers (at least standard awk can't, some versions such as GNU awk can). You can use bc to do the conversion. This works on all POSIX systems. { echo "ibase=16"; cat input.txt; } | bc | awk 'NR==1 {origin = $0-1} $0!=origin+NR {print "Out-of-sequence number at line", ...



Top 50 recent answers are included