I'm trying to write a bash shell script that will read the data from a given (as an argument) file, and for each row in the file, make a sub-directory under the given (as an argument) directory.

The script is named studentDir and the input file is named studentInfo.txt.
Here is two lines from it:

Sara Smith Freshman Marketing
James Lucas Junior Engineering

On the command line the user would write the script name, the txt file name, and the directory where the new directories should be stored. I think it would be like this:

$ studentDir studentInfo.txt .

Which will create the sub-directories in the current directory.

The directories should be named LLLLFF.
For example:


(The other info from the input file is not needed)

I think to get the names I would use:

DIRNAME=$(cut -d' ' -f2 | cut -c1-4 ; cut -d' ' -f1 | cut -c1-2) 
mkdir "$DIRNAME" 

But I'm not sure what command would create a directory for each row, and how I could do it recursively for each one.

  • Is your question how to iterate over each line in the file, or how to use the output from your cut command as the directory name? P.S. Recursion is rarely the answer (and in this case it is indeed not). Recursion is evil. Stay away from recursion :-) – Patrick Apr 21 '14 at 4:17
  • Hmm the question is how to use the output from the cut command as the directory name. I just need to make sure it does it for every line of the text file – Lacey Apr 21 '14 at 4:47
  • Do none of your users have a middle name? – terdon Apr 21 '14 at 11:07

awk solution

awk '{print substr($2,1,4) substr($1,1,2)}' file

gives you the directory names.

mkdir $(awk '{print substr($2,1,4) substr($1,1,2)}' file)

creates the directories (if they are not too many). For huge numbers (10,000+) you can use:

awk '{print substr($2,1,4) substr($1,1,2)}' file | xargs --delimiter=\\n mkdir

bash solution

awk is not necessary, the shell can do that itself:

while read first last rest; do mkdir -p "${last:0:4}${first:0:2}"; done <file
|improve this answer|||||
  • I think I follow. I've never used awk though. Is there a way to do it in bash? And I can replace 'file' with $1 I believe? Since it would be the first command-line parameter? – Lacey Apr 21 '14 at 4:35
  • @JackieLawrence file is the name of the file awk is supposed to read. – Hauke Laging Apr 21 '14 at 4:42
  • Using the While commands, couldn't I replace 'echo' with mkdir? So it would create the directory with that name rather than outputting. and for the <file , does the name need to be specified within the script, or will it reference the file that the user inputs? Thats what I meant with the $1 earlier. The user can input the file that they want to use this script with. – Lacey Apr 21 '14 at 5:01
  • @JackieLawrence echo was for my testing only, forgot to change that. file is a literal name. You can replace that by e.g. "$1" but I would always recommend to use something like "$file" instead in case the parameter definition of the script changes. – Hauke Laging Apr 21 '14 at 5:24

You could use perl. Saying:

perl -lanE 'mkdir substr(@F[1],0,4) . substr(@F[0],0,2)' studentInfo.txt

would create the desired directories.

|improve this answer|||||
  • I haven't learned to use perl yet either. Is there a way to do it in bash? – Lacey Apr 21 '14 at 4:49

Try this:

arr=($(cut -d ' ' -f1,2 < $*))
mkdir $(for ((i=0;i<${#arr[@]};i=i+2)); do echo ${arr[$i+1]:0:4}${arr[$i]:0:2}; done)

The first line will create an array with only the first 2 fields from the input. Each element in the array will have two fields (first, last). The second line will go through each element in the array and substitute each field according the requirement and make a new directory out of each new formed entry.

|improve this answer|||||
  • arr=($(cut -d ' ' -f1,2 < $*)) mkdir $(for ((i=0;i<${#arr[@]};i=i+2)); do echo ${arr[$i+1]:0:4}${arr[$i]:0:2}; done) – KB73 Aug 3 '16 at 15:40
  • Although this may be a correct answer, but because of its relative complexity, I would like to see an explanation of it. – Kusalananda Aug 3 '16 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.