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
  • 203
  • 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)"
steeldriver
  • 81,074