VincentG
VincentG

Reputation: 13

Recursively replace colons with underscores in Linux

First of all, this is my first post here and I must specify that I'm a total Linux newb.

We have recently bought a QNAP NAS box for the office, on this box we have a large amount of data which was copied off an old Mac XServe machine. A lot of files and folders originally had forward slashes in the name (HFS+ should never have allowed this in the first place), which when copied to the NAS were all replaced with a colon.

I now want to rename all colons to underscores, and have found the following commands in another thread here: pitfalls in renaming files in bash

However, the flavour of Linux that is on this box does not understand the rename command, so I'm having to use mv instead. I have tried using the code below, but this will only work for the files in the current folder, is there a way I can change this to include all subfolders?

for f in *.*; do mv -- "$f" "${f//:/_}"; done

I have found that I can find al the files and folders in question using the find command as follows

Files:

find . -type f -name "*:*" 

Folders:

find . -type d -name "*:*"

I have been able to export a list of the results above by using

find . -type f -name "*:*" > files.txt

I tried using the command below but I'm getting an error message from find saying it doesn't understand the exec switch, so is there a way to pipe this all into one command, or could I somehow use the files I exported previously?

find . -depth -name "*:*" -exec bash -c 'dir=${1%/*} base=${1##*/}; mv "$1" "$dir/${base//:/_}"' _ {} \;

Thank you! Vincent

Upvotes: 1

Views: 2955

Answers (1)

Will
Will

Reputation: 6721

So your for loop code works, but only in the current dir. Also, you are able to use find to build a file with all the files with : in the filename.

So, as you've already done all this, I would just loop over each line of your file, and perform the same mv command.

Something like this:

for f in `cat files.txt`; do mv $f "${f//:/_}"; done

EDIT:

As pointed out by tripleee, using a while loop is a better solution

EG

while read -r f; do mv "$f" "${f//:/_}"; done <files.txt

Hope this helps.

Will

Upvotes: 1

Related Questions