bash is not deterministicly processing the asterisk wildcard

06
2014-04
  • curios

    I accidentally added a user to my system without a home directory (I forgot to put the -d and -m flags in useradd). Rather than deleting the user and starting over I attempted to simply mkdir the home directory and copy over the files myself from /etc/skel. However, I received the following strange error:

    user@host:~$ sudo cp -rv /etc/skel/* /home/newuser/
    cp: cannot stat `/etc/skel/*': No such file or directory
    

    However, the following two commands work as expected:

    user@host:~$ sudo cp -rv /etc/skel/.bashrc /home/newuser/
    user@host:~$ cp -rv ~/testfolder1/* /testfolder2/
    

    Can anyone shed some light on why I received that initial error.

  • Answers
  • garyjohn

    The /etc/skel directory typically contains only hidden files, that is, those whose name start with a period. The shell expansion of * does not include hidden files unless an option is set for it do so. For bash, this option is set with shopt -s dotglob.

    In your case /etc/skel/* is not expanding to anything, so the shell leaves the argument as /etc/skel/*, but there is not file by that name.

  • glenn jackman

    When a glob expression (/etc/skel/*) expands to no files, then by default the expression is left in the command as a plain string. In this case it expands to no files because all the files in /etc/skel are dot files. So you were trying to copy the literal file "*" in /etc/skel, and that file does not exist.

    See http://www.gnu.org/software/bash/manual/bashref.html#Filename-Expansion


  • Related Question

    Wildcards in Word
  • Questioner

    I know little of wildcard usage in word.

    wildcards - case sensitive

    TO FIND

    enter mark                       ^13
    tab                              ^t
    any lowercase letter             [a-z]
    any uppercase letter             [A-Z]
    any letter                       [A-z]
    any digit                        [0-9]
    any no. between 6–9              [6-9]
    any letter between d–k           [d-k]
    any word contains only letters   ([A-z]@>)
    any word contains only digits    ([0-9]@>)
    for grouping (for replace)       (   )
    any character(s) between ...     (*)
    any para                         ^13(*)^13
    

    TO REPLACE

    To replace first group   \1
    To replace second group  \2
    enter mark               ^p
    tab                      ^t
    

    I want to know more about this. Can anyone help me?


  • Related Answers
  • daxim

    This looks like a non-standard notation for regular expressions, frequently abbreviated as regex or regexp. This is a tremendously important tool to learn if you do any serious text processing. As you have already understood, regex allow for powerful pattern matching and substitution. The notation you provided resembles the standard greatly, so I could recognise it. There is an industry standard, POSIX, and a de-facto standard, Perl regex. The next paragraph is boring history, skip it if you want.

    POSIX regex are used in many user-facing tools from POSIX-compliant operating systems (think Linux and its not-so-distant relatives). The canonical example is grep, which allows you to search for text in files. The text to match is specified in regex. Perl, a programming language, took the concept and extended it greatly for its purposes. Later a subset of this functionality was made it available as a code library, PCRE. All sorts of software embed this library, most notably text editors.

    I can see a few differences to what I am used to in the notation above. Word's symbol for symbol for escape sequences is ^, normally it is \. »Only digits« is used often, so it has an abbreviation in Perl, namely \d is equivalent to the character class [0-9]; similarly, \w means word characters and is equivalent to [0-9a-zA-Z_]. Word's notation appears cumbersome against it. I do not know the other limitations of Word, so I encourage you to switch to a text editor with PCRE support.

    You should learn first about whitespace matching (abbreviation \s) and repetition (+ and *). Perl's regex are explained in perlrequick, perlretut and perlre. To start experimenting right now, use the Flash based RegExr.

  • Charles Stewart

    Word's wildcards are regular expressions, with expressiveness between the Bash shell's extended globbing and Perl's PCRE regexes.

    Microsoft have two introductory articles, Add power to Word searches with regular expressions and Putting regular expressions to work in Word, that explains some of the main concepts.

    Cf. also a question I asked, What is the easiest way to do PCRE-style regexp search/replace for MS Word?