3

I use CentOS shared server environment with Bash.

ll "$HOME"/public_html/cron_daily/

brings:

./
../
-rwxr-xr-x 1 user group 181 Jul 11 11:32 wp_cli.sh*

I don't know why the filename has an asterisk in the end. I don't recall adding it and when I tried to change it I got this output:

[~/public_html]# mv cron_daily/wp_cli.sh* cron_daily/wp_cli.sh
+ mv cron_daily/wp_cli.sh cron_daily/wp_cli.sh
mv: `cron_daily/wp_cli.sh' and `cron_daily/wp_cli.sh' are the same file

This error might indicate why my Cpanel cronjob failed:

enter image description here

Did I do anything wrong when changing the file or when running the Cpanel cron command? Because both operations seem to fail.

  • I don't know if this can happen on Linux, but I recall a few cases on, I'm thinking, UNIX and MSDOS, where such "illegal" names had actually been created, presumably as a result of using a machine-language interface to manipulate/rename files, vs using the normal command and HL language interfaces. – Hot Licks Jul 15 '18 at 1:57
  • @HotLicks The only illegal names (at least on Linux) are an empty string, and a name with a slash (/) or null byte. You can make files with asterisks no-prob by quoting the asterisk or escaping it like this touch wp_cli.sh\*. – JoL Jul 15 '18 at 19:06
  • Similar: superuser.com/questions/178786/… – mgutt Aug 1 at 1:24
20

The asterisk is not actually part of the filename. You are seeing it because the file is executable and your alias for ll includes the -F flag:

-F

Display a slash ('/') immediately after each pathname that is a directory, an asterisk ('*') after each that is executable, an at sign ('@') after each symbolic link, an equals sign (`=') after each socket, a percent sign ('%') after each whiteout, and a vertical bar ('|') after each that is a FIFO.


As Kusalananda mentioned you can't glob all scripts in a directory with cron like that. With run-parts, you can call "$HOME"/public_html/cron_daily/ to execute all scripts in the directory (not just .sh) or loop through them as mentioned in this post.

  • 2
    Additionally, the cronjob fails because you can't execute all script in a directory like that. See unix.stackexchange.com/questions/454749/… – Kusalananda Jul 14 '18 at 17:28
  • Uh, how would "$HOME"/public_html/cron_daily/ run all scripts in the directory? cron will only run one command, and it won't use shell expansion. The easiest solution for OP would be to create a wrapper script that does for script in "$HOME"/public_html/cron_daily/*.sh; do $script; done, and then call the wrapper from cron. – nneonneo Jul 15 '18 at 1:36
  • @nneonneo Debian/Ubuntu already have run-parts, which does this, maybe other distributions have something similar? – Philipp Wendler Jul 15 '18 at 9:54
  • @nneonneo: Updated – Jesse_b Jul 15 '18 at 11:05
9

Jesse_b already answered the question, but I think it's worth to address some potential misconceptions.

The shell has characters that have special meaning under some specific conditions. For example: | is used in pipelines, > in redirections, \ to escape characters, etc. Those characters are not interpreted literally by the shell, so that's why when you do echo foo>bar, foo>bar won't be printed to your terminal, but foo will be redirected to the bar file.

Fortunately, the shell also has a mechanism which makes these characters to lose their special meaning: quoting. In POSIX shells, there are 3 quoting mechanisms:

  • Backslash \: preserves the literal value of the following character, with the exception of a <newline>.
  • Double-quotes "...": preserves the literal value of all characters within the double-quotes, with the exception of the characters `, $, and \.
  • Single-quotes '...': preserves the literal value of each character within the single-quotes, no exceptions.

So, following the previous example, if we wanted to print foo>bar literally, we could have done:

  • echo foo\>bar
  • echo "foo>bar"
  • echo 'foo>bar'

The asterisk * is one of those special characters, it is part of the pattern matching notation and is used for filename expansion. In other words, commands such as echo *.txt will replace the pattern with the files that the pattern matches.

In your case, cron_daily/wp_cli.sh* only matches cron_daily/wp_cli.sh, so mv sees 2 identical arguments and complains about it. That's fine because there's no cron_daily/wp_cli.sh* file. But if you had had an actual cron_daily/wp_cli.sh* file and more files that could be matched by the pattern, mv would have fail.

Consider the following scenario:

$ ls -l
total 0
-rw-rw-r-- 1 user group 0 jul 14 12:00 file*
-rw-rw-r-- 1 user group 0 jul 14 12:00 file1
-rw-rw-r-- 1 user group 0 jul 14 12:00 file2
-rw-rw-r-- 1 user group 0 jul 14 12:00 file3

If I try to rename file* without using quotes:

$ mv file* new_file
mv: target 'new_file' is not a directory

That's because these are the arguments that mv receives, thus new_file is expected to be a directory:

$ printf '[%s]\n' file* new_file
[file*]
[file1]
[file2]
[file3]
[new_file]

To successfully rename file*, I need to quote that argument:

$ mv 'file*' new_file
$ ls -l
total 0
-rw-rw-r-- 1 user group 0 jul 14 12:00 file1
-rw-rw-r-- 1 user group 0 jul 14 12:00 file2
-rw-rw-r-- 1 user group 0 jul 14 12:00 file3
-rw-rw-r-- 1 user group 0 jul 14 12:00 new_file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.