how to write foreach in one line in csh?
Asked Answered
C

6

13

Sometimes I use same foreach operation with different target files in csh.
If I can give foreach command in a single line, I could easily substitue the target file names to repeat the process.(I usually use `find . -name ...` for target files)
For the purpose of this question, let's assume I want to cat all the *.txt files.

$ foreach i (*.txt)
foreach? cat $i
foreach? end

I read https://unix.stackexchange.com/questions/32873/running-a-full-foreach-command and tried

alias disp 'echo "foreach i (*.txt)"; echo "cat "\$"i"; echo "end"; | /bin/csh'

when I type disp it gives me Invalid null command.
If I can do it in a single line, I could do !foreach:gs/\.c\>/.h/ (do the same replacing .c with .h). How can I do it?

Careerist answered 12/9, 2014 at 12:27 Comment(0)
A
16

This method works for me:

printf 'foreach f ( 1 2 3 )\n echo $f \n end' | tcsh
Andel answered 14/8, 2018 at 15:54 Comment(3)
Wow, This was a long un-answered question but your answer does it! Thanks!Careerist
there should be a line feed at the end printf 'foreach f ( 1 2 3 )\n echo $f \n end \n' | tcshMusquash
Is there any advantage of printf over just echo?Elk
A
4

There is no easy way to do the foreach in one line under tcsh.

However, by using alias, you may get something very close to your question.

alias disp 'foreach i (*.txt)\
  cat $i\
end'

You can call disp in your terminal.

If you want to direct the result into a pipe, then echo `disp` | grep foobar.

Sometimes, we need to save the result first, before further processing: set foo=`disp`

Amoy answered 26/6, 2017 at 20:5 Comment(3)
I like this answer better than the one that involves launching a child shell. The most common reason to want to do it in one line is for use as an alias and this solves it.Haberman
One down-side of this approach is that the history is messed up. It looks like: disp\n cat $i\n end\nHaberman
This is gold! My use case is to modify the current shell and this is perfect. I don't have the "messed up history" mentioned by @AllTheRage Thank you!Thrashing
T
0

Use bash -c:

$ bash -c 'for i in *.txt; do cat $i; done'

Tyner answered 20/4, 2018 at 12:56 Comment(0)
L
0

Aliases may serve as workaround, but may be painful and limited. Prefer to create a script or FIFO file. Here's an example as file.

echo '\
# Functions\
alias function '\''( set argv = ( \\\!* ) ; source ~/.cshfuncs )'\' >> ~/.cshrc
echo 'switch ("$1")\
  case 'disp':\
    shift\
    foreach i (*.txt)\
      cat "$i"\
    end\
    exit\
  default:\
    echo "Function $1 not set."\
    exit\
endsw' > ~/.cshfuncs

And here's an example as FIFO.

mkfifo ~/fifo
echo 'foreach i (*.txt)\
cat "$i"\
end' > ~/fifo & ( source ~/fifo )
Lheureux answered 30/10, 2023 at 21:28 Comment(0)
S
-1

For your first question, I don't know how to write this in .cshrc file directly.

But I will use another flexible way to do this.

1: Write a shell script: /home/user/disp.sh (or any path you want)

#/bin/bash
for line in `find . -name "*.c"`; do
echo ""
   cat "$line"
done

Or you only have csh shell:

#/bin/csh
foreach i (*.c)
    echo $i
end
  1. Add new alias command to the .cshrc file

    alias disp /home/user/disp.sh

  2. Reenter csh shell (or relogin)

    csh


For your second question, I did it on the same disp.sh script

This example is written in bash shell script.

#/bin/bash
usage() { echo "Usage: $0 [-d <depth>] [-e <extension>]" 1>&2; exit 1; }
while getopts ":d:e:" o; do
    case "${o}" in
        d)
            d=${OPTARG}
            ;;
        e)
            e=${OPTARG}
            ;;
        *)
            usage
            ;;
    esac
done
shift $((OPTIND-1))
if [ -z "${d}" ] || [ -z "${e}" ]; then
    usage
fi

for line in `find . -maxdepth ${d} -name "*.${e}"`; do
echo ""
   cat "$line"
done

You can simply type disp -d 1 -e c to find all .c file in the current path. (-d means the depth of the file which is started from current path, -e means extension of files)

Shoa answered 12/9, 2014 at 14:57 Comment(1)
Hi, I think you didn't get the question right. I wanted to use the whole foreach command in single line so that I can substitute a part of it and run the command again easily. In bash, I can do simply for i in 1 2 3; do echo $i; done .Careerist
G
-1

I tried to find answer but it looks there is no way. Just use bash by simply changing shell.

% bash

$ for f in *txt; do echo $f; done

$ exit

%

Gastronomy answered 19/5, 2017 at 2:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.