1

I am a marker and I have a whole lot of coursework files given to me in a folder with a structure like this:

student number --> coursework1 --> coursework.thy

Each student has one folder named student number which contains a single subfolder coursework1, and that subfolder contains a single file with extension .thy. Annoyingly, the files all have the same name coursework.thy Now, I want to name all the files after the student number of the student. In other words, I want to name the files not after the folder that contains them, but after the folder that contains the folder that contains them. I want to keep the original file extension.

Ultimately I would like to put all of these named files in a single folder (without subfolders) but I found a question answering that part of my issue: How do I move files out of nested subdirectories into another folder in ubuntu? (Trying to strip off many subfolders).

I want to do this using the terminal/bash ideally.

IIM
  • 113

2 Answers2

1

We cannot write the script for you, but I can help outline the steps and programming logic I would recommend.

First, you presumably have the /path/to/studentsnumbers/ where you are finding the folder structure you list above. Store that in a variable here we will call PathToStudNumbs.

PathToStudNumbs="/path/to/studentsnumbers/" 

Next there are a couple of useful tools you will want to explore: basename and dirname. These will obtain information about the elements of a path to a specific file. You may not need these for this case because all of the files you are changing are apparently named the same (coursework).

Since we don't know how you are iterating over your directories, I leave it to you to sort out what use basename and dirname will be to your specific situation.

Let's reframe how we see the current paths. We can rework that to something containing the elements we care about using variables. (I assume below the coursework number also changes over time.)

"${PathToStudNumbs}/${StudNumbs}/${courseworkNumb}/coursework.thy"  

If you work this into a cp statement to a different directory, it would look something like this:

cp "${PathToStudNumbs}/${StudNumbs}/${courseworkNumb}/coursework.thy" "${PathToDestination}/${StudNumbs}_${courseworkNumb}.thy" 

This would make a copy of the target file in a folder of your choosing where the new file would be named something like 123456_coursework1.thy (which is to say the student number, an underscore, the coursework number, and the file extension).

Or you could rename the existing file in place with mv, something like this:

mv "${PathToStudNumbs}/${StudNumbs}/${courseworkNumb}/coursework.thy" "${PathToStudNumbs}/${StudNumbs}/${courseworkNumb}/${StudNumbs}_${courseworkNumb}.thy" 

Ask questions if you'd like. I'll do what I'm able to assist.

JamesIsIn
  • 191
1

With Larry Wall's Perl rename

(prename on RHEL and derivatives, rename on Debian and derivatives):

Working in the top directory (the parent of the student directories):

rename -n 's:/coursework1/coursework::' */*/*.thy

In other words in studentnumber/coursework1/coursework.thy you delete /coursework1/coursework to be left with studentnumber.thy. Since on Unix filesystems "move" and "rename" are actually the same thing, the file will be moved to the top directory.

  • I am assuming that we are not dealing with tens of thousands of files here (otherwise the */*/*.thy would cause a too many arguments error)
  • It is not clear in your question if "coursework" is the true name or a variable, in the latter case you can use a regular expression instead:

    rename -n 's:/.+/[^.]+::' */*/*.thy
    
  • -n is for a dry run (so you can check what would be done), remove or replace by -v for actual execution.

  • If there are dots in the coursework name, the regex needs to be a bit more complicated (uses a look-ahead):

    rename -n 's:/.+/.+(?=\.thy)::' */*/*.thy
    
xenoid
  • 10,597