0

I have a directory that contains some nonsensically named files, for example:

apple_2020-01-01.txt
apple_2020-01-02.txt
orange_2020-01-01.txt
pear_2020-01-02.txt
pear_2020-01-03.txt
pear_2020-01-04.txt

I want to use a bash script to create some new files based on the timestamps on the files, one file for each unique timestamp.

There are some assumptions I can make:

1) the file names will always follow the format of fruit_*.txt

2) the files will either be named apple, orange, or pear

3) the timestamp will always be in the format of YYYY-MM-DD.

Based on the above example files, I'd expect the following files to be created by the script:

NewFile_2020-01-01.txt
NewFile_2020-01-02.txt
NewFile_2020-01-03.txt
NewFile_2020-01-04.txt

How can I achieve this?

2
  • 2
    What do you want in say NewFile_2020-01-01.txt - the contents of {apple,orange}_2020-01-01.txt or are you just after the filenames?
    – icarus
    Commented Feb 26, 2020 at 21:06
  • @icarus Just the file name. The contents would be empty, so creating them with a touch command would suffice. Commented Feb 26, 2020 at 21:07

3 Answers 3

2
#!/bin/bash
shopt -s nullglob
for file in {apple,pear,orange}_*.txt; do
    touch "NewFile_${file##*_}";
done

For each file, we remove the leading part until the underscore character, so only the timestamp and extension is left, and then prepend NewFile_ to the result.

touch will not complain if it tries to create a file that already exist.

This solution will also work if there are blank spaces after underscore.

2
  • Will this solution also work if there are extra characters before the first underscore, but before the timestamp? i.e. if the files were called apple_2020-01-01.txt, an_orange_2020-01-01.txt, and lots_of_pears_2020-01-01.txt, would the touch command still properly name the new files? Commented Feb 26, 2020 at 23:18
  • It will work under the question assumptions. Only files beginning with apple_, orange_ or pear_ and ending with .txt are considered by the script, as determined by the regex {apple,pear,orange}_*.txt. Files named otherwise are simply ignored. So if you add an_orange_1212-12-12.txt to the list in your question, you won't get NewFile_1212-12-12.txt, although one could easily adapt the script to take variations into account.
    – Quasímodo
    Commented Feb 27, 2020 at 0:02
0
#!/bin/bash
printf '%s\n' {apple,orange,pear}_*.txt | 
     sed 's/apple\|orange\|pear/NewFile' |
     sort -u |
     xargs touch

Use shell glob to get the filenames (this will fail if there are not any, and there are tens of thousands it could be a problem), used sed to change the names, then use sort -u to remove duplicates.

Finally feed them to xargs touch to create the files as per the OP's clarification comment.

0

ls *.txt | cut -f2- -d_ | sort -u | xargs -IX touch NewFile_X

  • cut gives the 2nd "field" with a delimiter of _

  • sort sorts and removes dupes (unique)

  • xargs runs the command touch and replaces X with what came in from the others

3
  • 1
    See mywiki.wooledge.org/ParsingLs
    – Ed Morton
    Commented Feb 26, 2020 at 21:16
  • For quick and dirty command line, using ls is perfectly acceptable. Commented Feb 26, 2020 at 21:16
  • 1
    We don't know if this is for a quick and dirty command line task or not. Maybe this is for some small part of a production system where the real files names contain newlines. Rather than guessing and not mentioning the issues, IMHO it's best if the OP has a heads up about the issues around parsing ls if that's the proposed solution to their problem.
    – Ed Morton
    Commented Feb 26, 2020 at 21:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .