0

I'm trying to iterate over all of the files/directories in a directory. That includes also all of the hidden files (without . and ..). From previous topic in Bash it was suggested to use:

for current in $1/$run_folder/{..?,.[!.],}*;
    echo current
done

I tried it in tcsh but it didn't work. How can I do it in tcsh?

vesii
  • 193
  • 3
  • 15
  • 1
    Instinctively, I would suggest executing the loop with `-exec` from `find`... Do you have a reason to avoid `find`? – Kusalananda Jun 14 '20 at 10:20
  • It should be a `tcsh` script with logic in the `for` loop (not just printing the `current`). so it will be long for `-exec` – vesii Jun 14 '20 at 10:23
  • 2
    Seeing as `-exec` can execute _arbitrary_ commands, that does not sound like restriction. As soon as you have a script that takes pathnames as command line arguments, you could execute it with `find "$1/$run_folder" -exec scriptname '{}' +` – Kusalananda Jun 14 '20 at 10:37
  • I want the `for` loop to be part of that script. In a shell script - iterate over the files/dirs in given path and do logic (like moving, removing and editing stuff). I don't want to have another script that does the logic. – vesii Jun 14 '20 at 10:40
  • Find -exec and xargs were developed precisely to meet this need. Don't assume limitations that don't exist. You might also explain "didn't work" in more detail: no files, wrong files. threw error, dumped kernel? – Paul_Pedant Jun 14 '20 at 11:22

1 Answers1

1

I rarely use tcsh, but you should be able to achieve what you want using the globdot option1:

  globdot (+)
           If  set,  wild-card glob patterns will match files and directo‐
           ries beginning with `.' except for `.' and `..'

So

#!/bin/tcsh

set globdot

foreach current ($1:q/$run_folder:q/*)
  printf '%s\n' $current:q
end

Beware it errors out with a No match error if there's no non-hidden file in the directory.

That can be worked around by including a wildcard known to match along with *:

#!/bin/tcsh

set globdot

set files = (/de[v] $1:q/$run_folder:q/*)
shift files

foreach current ($files:q)
  printf '%s\n' $current:q
end

BTW, the correct syntax for bash would be:

#! /bin/bash -
shopt -s nullglob dotglob
for current in "$1/$run_folder"/*; do
  printf '%s\n' "$current"
done

You had forgotten the quotes around your expansions, that echo can't be used for arbitrary data, and that by default non-matching globs are left unintended. The dotglob option (equivalent of csh/tcsh/zsh's globdot option) avoids the need for those 3 different globs.


Notes:

  1. The (+) indicates that the feature is "not found in most csh(1) implementations (specifically, the 4.4BSD csh)"
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
steeldriver
  • 78,509
  • 12
  • 109
  • 152