Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Post History

77%
+5 −0
Q&A In a bash shell script, how to filter the command line argument list to unique entries only, for processing each?

Here's an alternative that is a one-liner drop-in for your existing script: eval set -- $(printf "%q\n" "$@" | sort -u) It works by escaping the initial arguments, piping the escaped arguments ...

posted 3y ago by r~~‭  ·  edited 3y ago by r~~‭

Answer
#2: Post edited by user avatar r~~‭ · 2021-09-28T21:27:05Z (about 3 years ago)
  • Here's an alternative that is a one-liner drop-in for your existing script:
  • ```bash
  • eval set -- $(printf "%q\n" "$@" | sort -u)
  • ```
  • It works by escaping the initial arguments, piping the escaped arguments through `sort -u` which discards any duplicates, and then unescaping them with `eval` (which is often unsafe when handling untrusted input, but in this case you've escaped everything first so it's okay). `set --` alters the command line arguments to be whatever follows, so after this line is run, your `$1`/`shift` loop will be reading from the filtered list.
  • Put that before your main loop and you're golden.
  • Here's an alternative that is a one-liner drop-in for your existing script:
  • ```bash
  • eval set -- $(printf "%q\n" "$@" | sort -u)
  • ```
  • It works by escaping the initial arguments, piping the escaped arguments through `sort -u` which discards any duplicates, and then unescaping them with `eval` (which is often unsafe when handling untrusted input, but in this case you've escaped everything first so it's okay). `set --` alters the command line arguments to be whatever follows, so after this line is run, your `$1`/`shift` loop will be reading from the filtered list.
  • Put that before your main loop and you're golden.
  • (This does not remotely preserve argument order. The associative array approaches are better if you want the order of arguments to be the order in which the tasks are performed in the event of no duplicates. Since you said that doesn't matter to you, though, I thought this might be an approach worth considering.)
#1: Initial revision by user avatar r~~‭ · 2021-09-28T21:18:50Z (about 3 years ago)
Here's an alternative that is a one-liner drop-in for your existing script:

```bash
eval set -- $(printf "%q\n" "$@" | sort -u)
```

It works by escaping the initial arguments, piping the escaped arguments through `sort -u` which discards any duplicates, and then unescaping them with `eval` (which is often unsafe when handling untrusted input, but in this case you've escaped everything first so it's okay). `set --` alters the command line arguments to be whatever follows, so after this line is run, your `$1`/`shift` loop will be reading from the filtered list.

Put that before your main loop and you're golden.