2

I have a list of names in a text file (list.txt) I want to create a list of folders for the names included in that file. I wrote the following script, but it doesn't work and I don't know what is wrong:

#!/bin/tcsh
for name_id in `cat <path to list.txt>/list.txt` ; do
mkdir <name_id>${name_id}

The file list.txt and the scripts are in the same folder.

9
  • 1
    I don't know tsch, but if it's anything like bash, you probably need to terminate the do block with done? Also, you use name_id to start, then refer to subj_id.
    – Sparhawk
    Oct 16, 2014 at 22:09
  • for is bash, not tcsh.
    – Barmar
    Oct 16, 2014 at 22:10
  • The equivalent in tcsh is foreach, but it doesn't have a do clause. Also, you misspelled tcsh.
    – Barmar
    Oct 16, 2014 at 22:10
  • 2
    But it would be best not to use tcsh for scripting, use a POSIX-style shell. See faqs.org/faqs/unix-faq/shell/csh-whynot
    – Barmar
    Oct 16, 2014 at 22:11
  • Are you required to use tcsh or can you use any shell?
    – slm
    Oct 16, 2014 at 22:38

4 Answers 4

2

This worked for me:

xargs mkdir <list.txt

This works because if you give multiple arguments to mkdir it will happily create all the directories it can create. xargs simply "flattens" your text file by replacing newlines with spaces, thereby invoking mkdir with a long list of arguments containing all your directory names at once instead of one at a time.

If you want to add a fixed prefix (or suffix, or both):

xargs -I, mkdir prefix_, <list.txt

Whatever you put after the -I switch (a comma in this case) is replaced by the name that is read from the file.

One more thing, I would add quotes just in case the file names in your text file have spaces in them or other "special" characters:

xargs -I, mkdir "," <list.txt

or

xargs -I, mkdir "prefix_," <list.txt
1
  • It fails if list.txt contains ".
    – Ole Tange
    Nov 3, 2014 at 15:08
1

In your example, your confusing shell scripting commands. You have to pay special attention to which scripting language you're using and then adhere to its commands' syntax. In your example you're using turbo C shell (tcsh) however you're then mixing in Bash/Bourne shell commands and syntaxes.

You can use the following approach if you truly want tcsh. Say I had this sample file:

$ cat afile 
1
2
3
4
5

And this script:

$ cat cmd.csh 
#!/bin/tcsh

foreach i (`cat afile`) 
  echo "$i" 
end

Running it will produce this output:

$ ./cmd.csh
1
2
3
4
5

So to complete the task, we can add in the mkdir command after the echo:

$ cat cmd1.csh 
#!/bin/tcsh

foreach i (`cat afile`) 
  echo "making directory: $i" 
  mkdir "$i"
end

Now when we run it:

$ ./cmd1.csh 
making directory: 1
making directory: 2
making directory: 3
making directory: 4
making directory: 5

Resulting in the directories getting created:

$ ls -l
total 32
drwxrwxr-x. 2 saml saml 4096 Oct 16 18:58 1
drwxrwxr-x. 2 saml saml 4096 Oct 16 18:58 2
drwxrwxr-x. 2 saml saml 4096 Oct 16 18:58 3
drwxrwxr-x. 2 saml saml 4096 Oct 16 18:58 4
drwxrwxr-x. 2 saml saml 4096 Oct 16 18:58 5
-rw-rw-r--. 1 saml saml   11 Oct 16 18:47 afile
-rwxrwxr-x. 1 saml saml   86 Oct 16 18:56 cmd1.csh
-rwxrwxr-x. 1 saml saml   55 Oct 16 18:51 cmd.csh
3
  • Why echo I need mkdir ?
    – user88036
    Oct 16, 2014 at 22:53
  • @MJA - For demo purposes.
    – slm
    Oct 16, 2014 at 22:54
  • @MJA - see updates
    – slm
    Oct 16, 2014 at 22:59
1

If you have GNU Parallel you can do:

parallel -q mkdir '<name_id>'{} < list.txt 

Opposite xargs it deals correctly with special characters - such as <, >, ', " and space.

GNU Parallel is a general parallelizer and makes is easy to run jobs in parallel on the same machine or on multiple machines you have ssh access to.

Installation

If GNU Parallel is not packaged for your distribution, you can do a personal installation, which does not require root access. It can be done in 10 seconds by doing this:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

For other installation options see http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Learn more

See more examples: http://www.gnu.org/software/parallel/man.html

Watch the intro videos: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Walk through the tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html

Sign up for the email list to get support: https://lists.gnu.org/mailman/listinfo/parallel

0

You don't need a loop. You can do:

mkdir `sed 's/^/<name_id>/' <path to list.txt>/list.txt`
5
  • @Barmer. Thanks but I got the following message "name_id: No such file or directory"
    – user88036
    Oct 16, 2014 at 22:18
  • He's using a tcsh not a Bourne shell.
    – slm
    Oct 16, 2014 at 22:36
  • @MJA I assumed <name_id> was just a placeholder in your original question, and I just copied it here. You have to replace it with the actual prefix that you want to put at the front of every directory name in list.txt.
    – Barmar
    Oct 17, 2014 at 0:13
  • 1
    @slm I think my command should work in both tcsh and Bourne shell.
    – Barmar
    Oct 17, 2014 at 0:14
  • @Barmar - you're correct, I just tried it.
    – slm
    Oct 17, 2014 at 0:21

You must log in to answer this question.