Over my last several gigs, I was once asked to generate CSV's from a key database schema that could be loaded into Excel spreadsheets and archived for an Oracle database to be decommissioned. The context here is for a 12.2 Oracle database running on a dated version of Unix. Note that the solution I provide here doesn't include complexities of BLOB, CLOB, or other special field types.
There are some complexities in the context here. One is that although 12.2 and above have a CSV markup mode that can facilitate generate of simple structured tables in sqlplus, I ran into practical issues of a maximum size of concatenated strings (say, >4K character records) and embedded line feeds and ca::rriage returns (e.g., emails in varchar2 fields) which resulted in a violation of the one line per record objective. So I used the Unix shell tr command to strip these from the target file--but that left me with the problem of how to terminate the records. So basically I used the tilde (~) at the end of my concatenated string to mark the end of records and at the end replace the tilde's with line feeds using the tr command. This left me with another issue to consider: what if tilde's are embedded in your column data? I use the Oracle replace function to replace any tilde's in the data; if carriage returns, line feeds, and/or tilde's cannot be stripped or substituted, you may need to use a different approach.
I generate a PL/SQL script on the fly basically to work around the concatenated string limit in sqlplus; I use a caret (^) as my field delimiter and enclose fields in double-quotes. The first line of the CSV file consists of delimited column names. I assume here the use of a DBA-privileged OPS$ account (i.e., sqlplus / ) with the SID and Oracle binaries set in the environment and you are working in a write-privileged working directory, that you have sufficient storage available to accommodate multiple working copies of the target CSV file.
Finally, I assume an external file tablist in the working directory, consisting of capitalized target schema table names (one per line) with the schema name overlaying SOME_SCHEMA in the script.