Tag Info

New answers tagged

0

Following Kyle Jones advice to use available rsync options to do the job (instead of coding one) I've found rsync --include-from=file_to_exclude --recursive \ --delete-excluded \ /var/somedir/ /var/somedir/ to work just fine. I've also tried using --ignore-existing --ignore-non-existing --delete on multiple scenarios but the result was the same as without ...


0

Don't do this. It is a very bad idea to try to replicate what rsync include/exclude patterns do without using rsync. The fact that some of the patterns can be complex is even more reason not to attempt it. Use rsync itself to guarantee consistent behavior and minimize surprises. From the rsync manual page: --existing, --ignore-non-existing ...


9

If you want to loop over all the arguments to your script, in any Bourne like shell, it's: for i do something with "$i" done You could also do: for i in "$@"; do something with "$i" done but it's longer and not as portable (though is for modern shells). Note that: for i; do something with "$i" done is neither Bourne nor POSIX so should be ...


0

#!/bin/bash n=1 echo "$0 got $# args..." while [ $# -gt 0 ] ;do echo "$n: $1" shift n=$(( $n + 1 )) done Alternatively, look up 'Listing arguments with $* and $@' in http://www.tldp.org/LDP/abs/html/abs-guide.html which will elaborate on many aspects of these.


1

What does mv * do? Here's a shorter answer: The shell expands the wildcard * to a list of directory contents. Then the shell passes that full list to the command. The command never sees *. The command mv file1 file2 ... filen directory will move file1 ... filen into directory. Example Here I make a test directory containing three files $ mkdir t $ ...


0

To check what exactly mv command did, you may check it by adding echo before the command, so shell will expand all wildcards and print the result command, e.g.: $ echo mv /tmp/folder/* /* $ echo mv /tmp/* /* mv /tmp/launch-4TgsLB /tmp/skl /bin /dev /etc /home /lost+found /mnt /net /opt /private /sbin /tmp /usr /var So basically it'll move your files to ...


27

First I'll make a test base - 5 files and one folder: touch file1 file2 file3 file4 file5 mkdir folder Next I'll run a test command. The -v option specifies that I want every command the shell executes to be printed to stderr. The -x option specifies that I want the same printed to stderr - but I want it done after the command is evaluated but before the ...


3

Unquoted variables and command substitutions like $i or $(git …) apply the split+glob operator to the string result. That is: Build a string containing the value of the variable or the output of the command (minus final newlines in the latter case). Split the string into separate fields according to the value of IFS. Interpret each field as a wildcard ...


2

The wildcard pattern is expanded by the shell before the command is invoked. See G-Man's answer for a full explanation. Most shells require some form of intermediate command in order to apply a text transformation to the matches. Zsh offers a way to transform matches on the fly with its glob qualifiers: e or + to execute code for each match, which can ...


2

The point that you may be missing – that many people have trouble with, especially if they have experience with other operating systems before they come to *nix – is that, in many other OSs, wildcards on the command line are normally passed to the command to process as it sees fit.  For example, in Windows Command Prompt, rename *.jpeg *.jpg Whereas, in ...


0

Text streams like this should be read using a while loop rather than for, which is probably causing the issue (although I cannot reproduce it). A simple way to do this: git branch | while IFS= read -r line do echo "${line:2}" done Comparison: $ cd -- "$(mktemp -d)" $ git init Initialized empty Git repository in /tmp/tmp.MJFmu7q7EH/.git/ $ touch ...


0

This doesn't work because the shell tries to expand the entire string */test which doesn't exist yet. By default the string then expands to itself. If you're using Bash you may want to look at the various globbing options to handle this the way you want.


4

So I'll just give the answer for the question. You need to enable extglob to make bash recognize extended patterns besides the history expansion syntax. shopt -s extglob rm !(*keyword) shopt -s extglob also enables extended pattern matching on case and [[ ]] but it's already the default behaviour in [[ ]] starting Bash 4.1 and extended patterns are ...


0

When you run ls *, the first thing that happens is that the shell obtains a listing of the current directory. If the directory is huge and the server is slow, this could take a while. Once the shell has obtained the list of names of files in the current directory, it sorts that list (which is very quick compared to any network interaction), then calls ls. ...


1

You can disable the PATTERN(QUALIFIERS) syntax by unsetting the bare_glob_qual option: setopt no_bare_glob_qual If the option extended_glob is set (and you should set it, the only reason not to set it is for backward compatibility with rare scripts that use unusual syntax), then there is another syntax for glob qualifiers: PATTERN(#qQUALIFIERS). So you ...


2

Set the SH_GLOB option. setopt sh_glob From man zshoptions: SH_GLOB Disables the special meaning of (',|', `)' and '<' for globbing the result of parameter and command substitutions, and in some other places where the shell accepts patterns. If SH_GLOB is set but KSH_GLOB is not, the ...


1

Hypothesis: traversing a directory over NFS is speculatively loading more data than you would expect at once. Way too much IO on the server side, causing a single NFS call to take >20s. mount with intr option might allow Ctrl-C to interrupt the in-flight call. Google found a list of NFS calls which includes READDIRPLUS. Basically readdir + then stat for ...


0

There can be several reasons for the ls command to be slow on NFS directory. The directory might not be automounted. The machines may not be in the same network. However, this is a more general idea rather than specific to NFS. To list the files with out sorting, You can try ls -U which lists the files without sorting. From man page of ls, -U ...


4

No, globs are not expanded when quoted, so: set -- '*.txt' [ -f "$1" ] Will check whether the file called *.txt in the current directory is a regular file or a symlink to a regular file. [ -f $1 ] would be a problem ($1 would undergo word splitting (here not doing anything with the default value of $IFS) and filename generation). If you wanted to ...


3

With ls, you can do: ls -c -ltd -- *PRO*.PLI With find: find . ! -name . -prune -type f -name '*PRO*.PLI' (note that find will include hidden files like .xPRO.PLI while the shell glob (*PRO*.PLI) will not by default).


0

An unquoted variable or command substitution is not interpreted as a string, but as a list of filename wildcard patterns. That is, the value of the variable or the output of the command is split into separate pieces separated by characters in IFS (this step is called field splitting); then each piece is interpreted as a wildcard pattern, and if the pattern ...


4

The ? is a shell glob character used to match file names. It matches a single character. Thus, since you have a file named ab, the ?? pattern matches it. The reason this happens is because your parameter expansion is NOT quoted.


0

Ok, let's make it short: ls -1|xargs -i% bash -c 'mkdir %/doc;>>%/doc/doc1.txt' - We are on a directoy like your start directory. ls -11 lists herdir etc, one per line (there is nothing else) xarg runs a shell with a script argument, replacing the % by the directory For each directory: bash runs it's one string argument as a shell script, ...


8

In bash, use something like these lines: mkdir -p {mydir,hisdir,herdir}/doc touch {mydir,hisdir,herdir}/doc/doc1.txt The {...} syntax is called "brace expansion", and unlike pathname expansion, where the filename must exist, the generated results don't need to match anything already there. And the -p means create all nested components of the path as ...


0

for d in /*/ do [ -d "$d" ] || break f=$d/docs/doc1.txt mkdir -p -- "${f%/*}" touch -- "$f" done I think it meets your goals. Maybe I'm missing something though. Else you could: set -- /*/ [ -d "$1" ] && printf 'd=$%d mkdir -p -- "$d/docs" && touch -- "$d/docs/doc1.txt" ' $(seq "$#") | sh -s -- "$@" Or: set ...


5

With zsh: dirs=(*(/)) mkdir -- $^dirs/doc touch -- $^dirs/doc/doc1.txt (/) is a globbing qualifier, / means to select only directories. $^array (reminiscent of rc's ^ operator) is to turn on a brace-like type of expansion on the array, so $^array/foo is like {elt1,elt2,elt3}/doc (where elt1, elt2, elt3 are the elements of the array). One could also do: ...


1

You use Ubuntu, so you will have GNU find, try: find . -maxdepth 1 ! -iregex ".*\.\(jpg\|png\|gif\|xcf\)$" -exec mv -- -t /path/to/newdir "{}" + -iregex use regex to find filename, but case insensitive, ! negates the regex. -exec command + run command for files matching. It's like using find -print0 with xargs -0. Using this we can move multiple files ...


6

You can use find to find all files in a directory tree that match (or don't match) some particular tests, and then to do something with them. For this particular problem, you could use: find -type f ! \( -iname '*.png' -o -iname '*.gif' -o -iname '*.jpg' -o -iname '*.xcf' \) -exec echo mv {} /new/path \; This limits the search to regular files (-type f), ...



Top 50 recent answers are included