New answers tagged

1

If I understand what you're trying to do, you want to add the lines in file $ADD to file $TARGET, but without adding lines that already exist? I think there might be easier ways than repeated grepping. comm can give you the lines that only exist in the first, second, or both of two files, so let's use that: comm -23 <(sort "$ADD") <(sort "$TARGET") &...


3

You don't get a warning in bash, you get an error by ls. In both zsh and bash, {...} is not a globbing operator, it's an expansion that occurs before globbing. In: ls -d -- *.{dot,svg,err} (you forgot the -d and -- btw), the shell expands the {...} first: ls -d -- *.dot *.svg *.err and then does the glob. bash like most Bourne-like shells has that ...


2

Tack on (N) to the pattern; this tells zsh to not be upset about missing matching. rm -f *.{dot,svg,err}(N) It's a zsh glob feature. See man zshexpn for more details; under "Glob Qualifiers". It's annotated as "sets the NULL_GLOB option for the current pattern".


1

The simplest solution would be for f in *.gz; do test -f "$f" && gzip -d -- "$f" done or for f in *.gz; do [ -f "$f" ] && gzip -d -- "$f" done or even for f in *.gz; do if [ -f "$f" ]; then gzip -d -- "$f" fi done I'm all for verbosity if it help explain what the code does. The various shells have compact syntax for ...


7

With bash: shopt -s nullglob files=(/mydir/*.gz) ((${#files[@]} == 0)) || gzip -d -- "${files[@]}" With zsh: files=(/mydir/*.gz(N)) (($#files == 0)) || gzip -d -- $files Note that in zsh, without (N), like in pre-Bourne shells, csh or tcsh, if the glob doesn't match, the command is not run, you'd only do the above to avoid the resulting error message (...


3

One way to do this is: shopt -s nullglob for f in /mydir/*.gz; do gzip -d /mydir/*.gz break done The for loop with nullglob set on will only execute the loop at all if the glob has an expansion, and the unconditional break statement ensures that the gzip command will only be executed once. It's a bit funny because it uses a for loop as an if, but it ...


1

As a suggestion, you can add GLOBIGNORE=.:.. after the shopt -s extglob to avoid the rm: cannot remove '.': Is a directory error.


3

You need shopt -s extglob inside the script. Your bash configuration presumably turns this on automatically for interactive shells (perhaps because you load the bash-completion package for context-sensitive completion); you need to turn it on manually inside scripts. Also make sure that your script starts with #!/bin/bash (or a variant like #!/usr/bin/...


0

As has been already said, this is a "collating order" issue. The range a-z may contain upper case letters in some locales: aAbBcC[...]xXyYzZ | | from a to z The correct solution since bash 4.3 is to set the option globasciiranges: shopt -s globasciiranges to make bash act as if LC_COLLATE=C has been set in globing ...


0

Simply do: rm $(ls -I "*.txt" ) #Deletes file type except *.txt Likewise, if need to delete "except one or more file type", do: rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf


0

You can use backticks combined with ls -tr (sort by mod time and in reverse) like this: grep squiggle `ls -tr /var/log/messages*`


1

John1024 has added a good solution to your apparent problem, but based on the comments, you'd like to understand extglob better. I suspect that one of the core misunderstandings may have been that extglobs would work in a recursive manner -- that saying ./public_html/!(*uploads*) would exclude something named ./public_html/wp-content/uploads/. The globs (...


5

First, the extglob controls what ls sees on its command line. It does not control what ls does with what it sees on the command line. This is important because the -R option to ls tells ls to explore recursively any directories it sees on the command line. So, even if the *uploads* directories are not given explicitly on the command line, ls will find them ...


5

If the remote user is using bash then $HOME/.bashrc should be loaded, even in non-interactive shells. You can put your options there. e.g. $ head -1 .bashrc echo BASHRC loaded $ ssh localhost echo hello sweh@localhost's password: BASHRC loaded hello $


2

The source of the problem is that you have far too many small files. If I'm reading it right, you have over 14 million files. There is no way that ANY shell is going to be able to have over 14 million file names on the command line. Aside from that. your filenames seem to be about 18 characters long, so that's roughly 18*14M or about 252 megabytes just to ...


1

You obviously has a lot of files. Consider using GNU Parallel http://www.gnu.org/software/parallel/ The 'ls -U' does not sort the files and then it is faster. cd $VSTROOT/VirtualScreening/Ligands ls -U ZINC* | parallel echo {} \; pythonsh ../../prepare_ligand4.py -l {} -d ../etc/ligand_dict.py I don't understand why you echo it. Do you parse it on to a ...


1

I have solved the problem, let me share with you. I Rename the bash.csh to bash.sh, Next I change my script in order to run it in bash. Here is my new script to help in future for the same issue. #!/bin/bash cd $VSTROOT/VirtualScreening/Ligands/ for f in ZINC*.mol2 do echo "$f" pythonsh ../../prepare_ligand4.py -l "$f" -d ../etc/ligand_dict.py ...


6

Don’t parse the output of ls.  Just say foreach f (*).  Also, You should always quote your shell variable references (e.g., "$f") unless you have a good reason not to, and you’re sure you know what you’re doing.


6

Yes, they are (almost) completelly equivalent. Detail Inside a [ … ] construct: The = operator (or even the non-posix option of == ) tests string matching, not pattern matching. Inside a [[ ]] construct (from man bash): When the == and != operators are used, the string to the right of the operator is considered a pattern and matched according ...


4

Yes, changing the working directory back and forth is cumbersome and not really what you would like to do as it can lead to extremely weird situations in more complex scripts, unless you are careful. The usual method for changing the working directory for a simple command is to put the cd and to invocation of the command in a sub-shell. The working ...


3

You can do the following, when your current directory is parent_directory: for d in [a-z] do ( cd $d && your-command-here ) done The ( and ) create a subshell, so the current directory isn't changed in the main script.


-2

m=($f/FLA.*Image.*file.jpg) removed . and everything works fine m=($f/FLA*Image*file.jpg)


1

"FLA.*Image.*file.jpg" means literally FLA.*Image.*file.jpg and will not be expanded by ZSH. If you remove the " and add the parenthesis, like this m=($f/FLA.*Image.*file.jpg) the wildcards should then work. You have to explicitly surround the glob pattern with parentheses so that m is an array, otherwise m is a string and globbing is not done.


5

Stepping a bit sideways, using find might also be useful here if the command you are running for the files is simple enough to drop on one line. Find can take several paths to look in, and will happily find any files in subdirectories too. $ find foo/ bar/ -name "*.jpg" -exec echo {} \; foo/ccc.jpg foo/bbb.jpg bar/aaa.jpg (The command executed is given ...


12

This is normal and default behavior: If globbing fails to match any files/directories, the original globbing character will be preserved. If you want to get back an empty result instead, you can set the nullglob option in your script as follows: $ shopt -s nullglob $ for f in "$my_dir"*."$ext"; do echo $f; done $ You can disable it afterwards with: $ ...


1

add this line to the start of your script shopt -s nullglob


5

Because when you use just *net* (without any quoting or escaping), it will be expanded by the shell as the (existing) net file/directory in the current directory before the find command run. So the command becomes: find . -name net As you can see it is just matching net, so usbnet.ko will not be matched. Also note that, without quoting and escaping, if ...



Top 50 recent answers are included