Reputation: 479
I have a file full of filenames and directory names. Example:
DIR,/mnt/sdcard/mydir1/
DIR,/mnt/sdcard/mydir2/
DIR,/mnt/sdcard/mydir3/
FILE,/mnt/sdcard/mydir1/file1.txt
FILE,/mnt/sdcard/mydir2/file1.txt
FILE,/mnt/sdcard/mydir3/file1.txt
with total around 30.000 entries of directories and filenames. I need to create all the directories, sub-directories and files (empty ones) inside a specified folder. And I also want to skip all the directories/files that already exist!
Currently I have this, but I am hoping there is a better way, as this is very slow and consumes a lot of CPU:
#!/bin/bash
cd /home/mydir/dummydir/
for file in *.tree.txt; do
MEMBER=$(echo $file | cut -d '.' -f1)
DIRECTORY=/home/mydir/dummydir/$MEMBER
while read line
do
if [[ $line == FILE,* ]]
then
CUTOFFILE=$(echo "$line" | cut -c 6-)
touch "$DIRECTORY$CUTOFFILE"
else
CUTOFFDIR=$(echo "$line" | cut -c 5-)
if [[ ! -d "$DIRECTORY$line" && $line == DIR,* ]]; then
mkdir -p "$DIRECTORY$CUTOFFDIR"
fi
fi
done < $file
done
Upvotes: 0
Views: 2669
Reputation: 361595
#!/bin/bash
cd /home/mydir/dummydir/
for file in *.tree.txt; do
dir=${file%.tree.txt}
while IFS=, read type path; do
case $type in
FILE) touch "$dir/$path";;
DIR) mkdir -p "$dir/$path";;
*) echo "bad line: $type,$path" >&2;;
esac
done < "$file"
done
I'm not a huge fan of cut
, so I replaced it with other parsing methods.
With each line containing two fields separated by a comma, you can cut out a lot of code by having read
parse the line and store the two parts in separate variables. You can do that by temporarily overriding the $IFS
variable with IFS=,
which tells read
to use ,
as the field separator. Then read type path
reads the two parts into $type
and $path
.
Both touch
and mkdir -p
are harmless when applied to files or directories that already exist, so you could probably omit the checks for existing files and just always do them.
Since you start the script by cd
ing to /home/mydir/dummydir
, you don't really need to repeat that later.
${file%.tree.txt}
is a shorter way of stripping off .tree.txt
. Another way is $(basename "$file" .tree.txt)
.
Upvotes: 3