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>
source to share
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"
source to share
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.
source to share