How can I list files in a folder and insert each line from that list into * .plist via terminal?

I have several files in a folder (with * .m4r extension) and I need to copy each of their names to another (with * .plist extension).

For example,

Folder=/Library/Ringtones

      

Files in this folder:

 - name_of_first_file.m4r
 - name_of_second_file.m4r
 - name_of_third_file.m4r

      

Plist (where we have to add the names of these files):

Plist=/System/Library/PrivateFrameworks/ToneKit.framework/TKRingtones.plist

      

what i need at the end in this plist file:

<string>system:name_of_first_file</string>
<string>system:name_of_second_file</string>
<string>system:name_of_third_file</string>

      

Also I don't know how many files are in the Folder . It can have 1 or 2, or even 100!

Could you please tell me how can I do this using bash in Terminal! Thank!


ANSWER TO John1024

This code works. Thanks to

     #!/bin/bash
     cd /Library/Ringtones
     Plist="/System/Library/PrivateFrameworks/ToneKit.framework/TKRingtones.plist"
     for file in *.m4r; do printf '<string>system:%s</string>\n' "$file" ; done >>"$Plist"
     exit 0

      


I've got one more question.

1 The TKRingtones.plist stock layer is located here (/System/Library/PrivateFrameworks/ToneKit.framework/)

     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0">
     <dict>
        <key>classic</key>
        <array>
            <string>system:unlock</string>
            <string>system:Alarm</string>
            <string>system:Ascending</string>
        </array>
        <key>modern</key>
        <array>
            <string>system:Apex</string>
            <string>system:Beacon</string>
        </array>
        <key>sort</key>
        <true/>
     </dict>
     </plist>

      

How can I make the script (which you suggested) insert lines after the array ?

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>classic</key>
        <array>
    <string>system:NAME_OF_FIRST_FILE</string> <<<<<<<<<<<<<<<ADD HERE 
    <string>system:NAME_OF_SECONDS_FILE</string> <<<<<<<<<<<<<<<ADD HERE
    <string>system:NAME_OF_THIRD_FILE</string> <<<<<<<<<<<<<<<ADD HERE
            <string>system:unlock</string>
            <string>system:Alarm</string>
            <string>system:Ascending</string>
        </array>
        <key>modern</key>
        <array>
            <string>system:Apex</string>
            <string>system:Beacon</string>
        </array>
        <key>sort</key>
        <true/>
    </dict>
    </plist>

      

+3


source to share


2 answers


In the future, try to put all the information in your question from the very beginning!

Printing multiple filenames is relatively straightforward; inserting them in the correct location in an existing structured file is generally somewhat more difficult. I decided to use awk for input; it uses John1024 change script internally to get * .m4r filenames.



#!/usr/bin/env bash

# Copy all .m4r filenames in "/Library/Ringtones" into the XML file $Plist
# Written by PM 2Ring 2014.11.09

Plist="/System/Library/PrivateFrameworks/ToneKit.framework/TKRingtones.plist"

cd "/Library/Ringtones"

#Make a backup of the current Plist
cp -p "$Plist" "$Plist.bak"

#Read from $Plist.bak, inserting new *.m4r names
# after the first <array> tag, and save to $Plist
awk '
$1 == "<array>" && ! copied {
    print
    while (( "for i in *.m4r; do echo ${i%.m4r}; done" | getline ) > 0)
        printf "    <string>system:%s</string>\n", $0
    copied = 1; next
}
{print}' "$Plist.bak" > "$Plist"

#View modified file to make sure it correct
cat "$Plist"

      

0


source


for file in *.m4r; do printf '<string>system:%s</string>\n' "$file" ; done >>"$Plist"

      

The result looks like this:

<string>system:name_of_first_file.m4r</string>
<string>system:name_of_second_file.m4r</string>
<string>system:name_of_third_file.m4r</string>

      

Explanation

  • for file in *.m4r; do

    This will loop over every file in the current directory whose name ends in .m4r

    .

    This loop will work even if filenames include spaces, tabs, or other complex characters.

  • printf '<string>system:%s</string>\n' "$file"

    This prints the desired line containing the filename.

  • done

    This signals the end of the cycle for

    .

  • >>"$Plist"

    This causes all of the output from that loop to be appended to the file specified by the shell variable Plist

    .



Answer to the revised question

This loop reads the Plist file until it finds a line <array>

, then writes out the new values ​​(as we did above), and then finishes copying the Plist file:

while IFS= read -r line
do
    printf "%s\n" "$line"
    case "$line" in
        *"<array>"*)
            for file in *.m4r
            do_
                printf '       <string>system:%s</string>\n' "$file"
            done
            ;;
    esac
done >"$Plist.tmp" <"$Plist"
mv "$Plist.tmp" "$Plist"

      

This should work in any POSIX shell.

+1


source







All Articles