1

I get to understand that this code is for bash shell

for f in $file.docked.[0-9][0-9][0-9]
do
  mv $f $f.pdb
done

And this code is for tcsh shell

foreach f ( file.docked.[0-9][0-9][0-9] )
  mv $f $f.pdb
end

This I understood after reading from references. As a learner, I had the perception that both the codes will work in bash. Is there a way to find out which shell a particular code will work without full knowledge about the different shell. Extending is there a way to make code work on all the shell independent of the type of shell of Linux it was written on?

Praveen Kumar-M
  • 592
  • 5
  • 15
  • 5
    Can't resist mentioning https://unix.stackexchange.com/a/71137/117549 – Jeff Schaller May 31 '20 at 16:30
  • 2
    Ordinarily, one knows what language one writes code in. You may treat each shell as a separate language. If you write bash code, don't expect to be able to run it with sh or tcsh or zsh. It may work, just like running some Python statements with a Perl interpreter may possibly work, but it would be based on luck, mostly. Usually, the correct interpreter is indicated by the #! line at the top of the script. – Kusalananda May 31 '20 at 16:53
  • @JeffSchaller I really wish you had not mentioned that page. It gives me a headache just looking at it. :) – doneal24 May 31 '20 at 17:15
  • 2
    When writing the code specify the interpreter at the top (in the first line): e.g. #!/bin/bash – ctrl-alt-delor May 31 '20 at 21:44
  • 1
    I sympathize to an extent, but the mainstream English usage is that "code" is an uncountable noun in contexts such as these, – JdeBP Jun 01 '20 at 02:45
  • @JeffSchaller♦, thanks for providing a link to some really interesting material – jsotola Jun 01 '20 at 04:50
  • See also http://www.faqs.org/faqs/unix-faq/shell/shell-differences/ – tripleee Jan 08 '23 at 17:32

1 Answers1

6
for f in $file.docked.[0-9][0-9][0-9]
do
mv $f $f.pdb
done

Is syntactically valid code in csh, tcsh and all shells of the Bourne family (ash, bash, zsh, ksh, zsh, mksh, yash...) but it's in zsh that it's most likely to be doing something useful.

If the intent of that code is to add a .pdb suffix to the names of files in the current directory that start with the contents of the $file shell variable and end in .docked. followed by 3 ASCII decimal digits, in bash, you'd need:

shopt -s failglob
for f in "$file".docked.[0123456789][0123456789][0123456789]
do
mv -- "$f" "$f.pdb"
done

(the -- is needed regardless of the shell) as in bash

  • like in the Korn shell, you need to quote parameter expansions as otherwise they undergo split+glob
  • [0-9] generally matches a lot more characters than just 0123456789, the list of which varies with the locale and the system. You need [0123456789] in bash to match on 0123456789 only (and no, the globasciiranges option of recent versions doesn't help).
  • globs are left unexpanded when they don't match, so you'd get one pass in the loop with a $f containing contents-of-file-variable.docked.[0-9][0-9][0-9] if there was no matching file. failglob (to get a behaviour similar to that of csh or zsh) or nullglob (an option copied from zsh) address that.
foreach f ( file.docked.[0-9][0-9][0-9] )
  mv $f $f.pdb
end

Does look like csh syntax, but again that's rather zsh syntax. In (t)csh that should rather be:

foreach f ( file.docked.[0-9][0-9][0-9] )
  mv -- $f:q $f:q.pdb
end

(though in that particular case, the :qs are not strictly necessary as contrary to the other sample, the file names are guaranteed not to contain SPC, TAB, LF or wildcard characters).

Writing code that is valid and does the same thing in completely different languages is very tricky. It's generally called polyglot coding. The Code Golf stackexchange sister site has a section for that. But that's not the kind of thing you would want to do normally.

See this example on this site as an example of the kind of length you need to go to to achieve it.