Reputation: 3750
Pretend my root was:
foo
I have a folder structure of:
-foo
-123
-file.jpg
-file2.jpg
-456
-file.jpg
-file2.jpg
The directory could potentially be a few folders deeper.
If I had the root as such:
ROOT=foo
How would I go about listing every filename and their path in a CSV sort of format in a shell script?
I tried a few of the answers but I'm struggling to make it output a long string of CSV.
I'd expect something like:
file.jpg,123,file2.jpg,123,file.jpg,456,file2.jpg,456
So, I tried this:
# make a var for files in current folder
arr=(./*)
CSVRETURN=""
# simple loop to iterate files
for ((i=0; i<${#arr[@]}; i++)); do
#do something to each element of array
CSVRETURN="$CSVRETURN","${arr[$i]}"
done
echo $CSVRETURN
It keeps adding periods to my output and I don't believe I even have the recursive portion correct. Could somebody please point me in the right direction or a doc that may help?
I've done very little with shell scripts but I'm trying :) Basically going to take this answer and export to a CSV for an entire directory and provide links for images with their dir path (relative to initial dir) for easy filtering to import to Excel.
Upvotes: 0
Views: 1486
Reputation: 1319
Instead of bash
, this can be easily done if you have GNU find
find foo -type f -printf '"%f","%h"\n' | paste -d, -s -
%f
for filename%h
for leading directory pathpaste -d, -s -
concatenates newline separated result into a comma separated single lineOr a more general solution with BSD find
since it does not support the -printf
option
find foo -type f -print | sed 's|^\(.*\)/\(.*\)|"\2","\1"|' | paste -d, -s -
Output
"file1.jpg","foo/123","file2.jpg","foo/123","file1.jpg","foo/456","file2.jpg","foo/456"
To generate a quick test case, you can use
mkdir -p foo/{123,456}
touch foo/{123,456}/file{1..2}.jpg
to produce a directory structure like
foo/
├── 123
│ ├── file1.jpg
│ └── file2.jpg
└── 456
├── file1.jpg
└── file2.jpg
Upvotes: 1
Reputation: 6180
Since you want:
You could have two conventions (based on my understanding of your example):
full/folder/file , full/folder/file
full/folder , file , full/folder , file
Assuming my current directory foo looks like this:
14:37:14 ツ :foo >ls -R
sublevel1 456 123
./sublevel1:
123
./sublevel1/123:
file2.jpg file.jpg
./456:
file2.jpg file.jpg
./123:
file2.jpg file.jpg
Then for the first convention:
#!/usr/bin/env bash
first=1
find . -type f -print0 | while IFS= read -rd '' file ; do
if [ "$first" == "1" ]; then
filestr="\"$(cut -f2- -d'/' <<< "${file}")\""
unset first
else
filestr=",\"$(cut -f2- -d'/' <<< "${file}")\""
fi
printf "%s" "$filestr"
done
This would give you the following result:
"sublevel1/123/file.jpg","sublevel1/123/file2.jpg","456/file.jpg","456/file2.jpg","123/file.jpg","123/file2.jpg"
If you changed the -print0
to -printf "%h\0%f\0"
, then you'd get an output like the second convention above:
"sublevel1/123","file.jpg","sublevel1/123","file2.jpg","456","file.jpg","456","file2.jpg","123","file.jpg","123","file2.jpg"
Notes:
printf "%s"
format is fairly resilient in it's handling of names also when the string is passed to the program properlyif
block is just to ensure a comma is not prefixed to the very first fileFor more robust applications, consider serialized JSON, or some other data representation format where processing of lists can be handled in a more complete manner.
Upvotes: 0