What is happening
The shell (bash) sees the argument
[a-z]. That's a wildcard pattern (a glob), which matches any lowercase letter¹. Therefore the shell looks for a file name that matches this pattern. There are three cases:
- No file in the current directory has a name that is a single lowercase letter. Then the shell leaves the wildcard pattern unchanged, and
tr sees the arguments
[a-z]. This is what happens on most of your machines.
- A single file in the current directory has a name that is a single lowercase letter. Then the shell expands the pattern to this file name, and
tr sees the arguments
-d and the file name. This happens on the server, and the matching file is called
o since we can see that
tr deleted the letter
- Two or more files in the current directory have a name that is a single lowercase letter. Then the shell expands the pattern to the list of matching file names, and
tr sees three or more arguments:
-d and the file names. Since
tr expects a single argument after
-d, it will complain.
What you should have done
If there are special characters in the argument of a command, you must escape them. Put the argument in single quotes
'…' (this is the simplest way, there are others). Inside single quotes, all characters stand for themselves except the single quote itself. If there is a single quote inside the argument, replace it by
tr -d '[a-z]'
However note that this is still probably not what you meant! This tells
tr to delete lowercase letters and square brackets. It's equivalent to
tr -d ']a-z[',
tr 'a-z', etc. To delete lowercase letters, use
tr -d a-z
The argument to
tr is a character set. You put brackets around a character set in a regular expression or wildcard pattern to indicate that it's a character set. But
tr works on a single character at a time. Its command line arguments are what you'd put inside the brackets.
You do need brackets to indicate character classes. In a regular expression, you use brackets inside brackets to indicate a character class, e.g.
[[:lower:]]* matches any number of lowercase letters,
[[:lower:]_]* matches any number of lowercase letters and underscores. In the argument of
tr, you need the set without its surrounding brackets, so
tr -d '[:lower:]' deletes lowercase letters,
tr -d '[:lower:]_' deletes lowercase letters and underscores, etc.
¹ In some locales it may match other characters.