ls: listing filenames without directories?
So my boyfriend's GSI for one of his classes told him there's a way you can use ls (not find) to list filenames one-per-line, in BASH without including directories. I think he was either wrong or making that up. There is a way to list just the names and one per line but there aren't any arguments I can find that can be used to exclude directories.
Anyone have a clue? Here's the only way I've been able to do it thus far but apparently isn't what he meant: Code:
IFS=', '; files=`ls -m`; for i in $files; do if [ -f $i ]; then echo $i; fi; done Quote:
Quote:
Quote:
Thanks in advance! |
Could it be something like ls -1 (<-this is the number 1) */ This lists the directory contents one per line and only shows the directory name where the files reside.
Code:
ls -1 */ |
It's these little "puzzles" that aggravate me. The "solution" never matches the expectation you have after the initial presentation of the problem. Given that this is from an academic setting, the solution is probably not usable in any practical sense--just a curiosity.
That said, you need more information, but here are some "answers" with varying levels of cheesy-ness: 1. ls is open source--go rewrite it to exclude directories by default 2. enforce a naming scheme for your directories (e.g. "all directories must start with an underscore"). In that case, you can use the "--hide" or "--ignore" options to filter the directories from the output more serious approaches: 3. ls can take a list of files on the command-line. So you can have a command in this form: "ls <args1> `ls <args2>`" I experimented with the -p option (which adds a trailing slash '/' to directory entries) as part of args2 and then tried --hide="*/" as part of args1, but didn't get anywhere. 4. there may be an approach with globbing in the shell. I glanced through the man page, and saw reference to using "**" and "**/" as special globs/wildcards. I didn't look that hard or experiment at all. a non-ls-exclusive solution: The above assumes you can only use ls, but if you can use another tool, this should work easily: ls -l | grep -v "^d" or the "reverse" of the same command: ls -l | grep "^-" As a side note, there have been a number of "how do I display directories only" types of threads in the past. You might find some inspiration in them. But most of them will probably use the pipe-into-grep solution above. |
Displaying directories only is rather easy.
Code:
ls -d */ Code:
ls -p | grep -v /$ The only direction I can think to go, if there is a solution to this, is through globbing or some other path matching trickery. As a simple example, if you could be sure that files have extensions, while directories don't (a poor assumption of course), then this would work. Code:
ls *.* PS. ** is the new bash.v4 recursive listing option. It's disabled by default, so use shopt -s globstar to enable it. But I don't think it will likely have much use in this situation, unless the challenge is expanded to include recursiveness too. |
Quote:
One thing about that: you probably wouldn't be able to preserve any color-coding (e.g. if you used ls -p --color=auto, or if you have ls aliased to ls --color=auto as I do :)). |
Quote:
But then again this is just another variation of what's been pointed out before; that it's possible, indeed easy, when you can use an external tool to parse the output. There are likely dozens of good solutions you could come up with using various programs. I already have some ideas about how it could be done using various shell scripting techniques. The challenge as I see it is whether there's any way to do it using only ls, and nothing else that could be considered a command (executable or shell built-in). In other words, things like globbing and needing to have certain shell options enabled first would be acceptable, but scripting mechanisms like loops and especially test probably wouldn't. I'm starting to believe there isn't any way to do it. On the other hand there are other questions about the challenge that are even less clear. Long format, short format, any format? Current directory only, or recursive as well? It might help if we knew exactly what the expected output would be. |
Yeah, IF it's possible, it will likely depend on both ls and the shell environment.
I played with things a little more because David's post got me thinking. I combined his any my approach. Rather than describe with words, here's what I tried: Code:
ls -1 --hide=`ls -d */` Unfortunately, the "PATTERN" as described in the man page for --hide won't accept and use the ls output like we want. For this approach to work, the interior directory listing would need it's output changed to use a vertical bar between the directory names. I saw no way of convincing ls to use those bars (which would need to be escaped mind you--otherwise the shell might see them as pipes--depending on the order of expansion/inerpretation). Also, when thinking about that, I realized (again) how the shell handles things. The fileglobbing expansion happens before ls is executed. That makes me believe the environment is really the key as opposed to ls. So, if the original question does indeed have a solution, it's more likely the result of the shell's fileglobbing, and we've assumed bash so far. I have little experience with tcsh, but that's a possibility. tcsh is more C-like in its syntax and hence, more "familiar" especially in a computer curriculum. There's also ksh, ash, and who knows how many others. Each handles fileglobbing differently. |
All times are GMT -5. The time now is 10:52 PM. |