Windows RENAME komutu joker karakterleri nasıl yorumlar?


77

Windows RENAME (REN) komutu joker karakterleri nasıl yorumlar?

Yerleşik YARDIM tesisi hiçbir işe yaramaz - joker karakterlere hitap etmez.

Microsoft TechNet XP online yardım çok daha iyi değildir. İşte joker karakterlerle ilgili tüm söyleyebilecekleri:

"Her iki dosya adı parametresinde joker karakterler ( *ve ?) kullanabilirsiniz. Dosya adı2'de joker karakterler kullanırsanız, joker karakterler tarafından temsil edilen karakterler, dosya adı1'deki karşılık gelen karakterlerle aynı olacaktır."

Çok fazla yardım yok - ifadenin yorumlanmasının birçok yolu var.

Dosya adı2 parametresindeki joker karakterleri bazı durumlarda başarıyla kullanabildim , ancak her zaman deneme yanılma oldu. Neyin işe yarayıp neyin işe yaramadığını tahmin edemedim. Sık sık, her yeni adı gerektiği gibi oluşturabilmem için her bir adı ayrıştıran bir FOR döngüsü bulunan küçük bir toplu komut dosyası kullanmak zorunda kaldım. Çok uygun değil.

Joker karakterlerin nasıl işlendiğinin kurallarını bilsem, RENAME komutunu daha fazla parti yapmak zorunda kalmadan daha etkili bir şekilde kullanabileceğimi düşündüm. Elbette kuralları bilmek de toplu gelişim için faydalı olacaktır.

(Evet - bu, eşleştirilmiş bir soru ve cevap gönderdiğim bir durumdur. Kuralları bilmemekten bıktım ve kendi başıma denemeye karar verdim. Başkalarının keşfettiğim şeyle ilgilenebileceğini düşündüm.)


Burada joker karakterlerle nasıl yeniden adlandırma yapılacağına dair iyi örnekler var: lagmonster.org/docs/DOS7/z-ren1.html
Matthew Lock

5
@MatthewLock - İlginç bağlantı, ancak bu kurallar ve örnekler Windows için değil MSDOS 7 içindir . Önemli farklılıklar var. Örneğin, MSDOS *, Windows'tan sonra ek karakterlerin eklenmesine izin vermez. Bunun çok büyük sonuçları var. Keşke o site hakkında bilseydim; soruşturmamı kolaylaştırabilirdi. MSDOS7 kuralları, eski DOS kurallarından, uzun dosya adlarından önce önemli ölçüde farklıdır ve Windows'un bunu nasıl yönettiği yönünde bir adımdır. Önceden uzun bir dosya adı DOS kuralları bulmuştum ve soruşturmam için değersizdiler.
dbenham

Bunu bilmiyordum;)
Matthew Lock

Yanıtlar:


116

Bu kurallar bir Vista makinesinde yapılan kapsamlı testlerden sonra keşfedildi. Dosya adlarında unicode ile test yapılmamıştır.

RENAME, 2 parametre gerektirir - bir sourceMask, ardından bir targetMask. Hem sourceMask hem de targetMask, *ve / veya ?joker karakterler içerebilir . Joker karakterlerin davranışı, kaynak ve hedef maskeler arasında biraz değişir.

Not - REN bir klasörü yeniden adlandırmak için kullanılabilir, ancak joker edilir değil bir klasörü yeniden adlandırma zaman sourceMask veya targetMask Ya izin verdi. SourceMask en az bir dosyayla eşleşiyorsa, dosya (lar) yeniden adlandırılacak ve klasörler göz ardı edilecektir. SourceMask yalnızca dosyalarla değil, dosyalarla eşleşiyorsa, kaynakta veya hedefte joker karakterler belirirse sözdizimi hatası oluşur. SourceMask hiçbir şeyle eşleşmezse, "dosya bulunamadı" hatasıyla sonuçlanır.

Ayrıca, dosyaları yeniden adlandırırken joker karakterlere yalnızca sourceMask dosyasının dosya adı bölümünde izin verilir. Dosya adına giden yolda joker karakterlere izin verilmez.

sourceMask

SourceMask, hangi dosyaların yeniden adlandırıldığını belirlemek için bir filtre olarak çalışır. Joker karakterler burada dosya adlarını filtreleyen diğer komutlarla aynı şekilde çalışır.

  • ?- 0 veya 1 karakter hariç herhangi bir karakterle eşleşir . Bu joker karakter açgözlüdür - bir değilse, her zaman bir sonraki karakteri kullanır. .Ancak, adın sonunda veya bir sonraki karakter bir.

  • *- Aşağıdakiler de dahil olmak üzere, 0 veya daha fazla karakterle eşleşir. (aşağıda bir istisna dışında). Bu joker açgözlü değildir. Sonraki karakterlerin eşleşmesini sağlamak için gerektiği kadar az veya gerektiği kadar eşleşir.

Tüm joker karakter olmayan karakterler, birkaç özel durum istisnasıyla kendileriyle eşleşmelidir.

  • .- Başka karakter kalmazsa, kendisi ile eşleşir veya adın sonu (hiçbir şey) ile eşleşebilir. (Not - geçerli bir Windows adı ile bitemez .)

  • {space}- Başka karakter kalmazsa, kendisi ile eşleşir veya adın sonu (hiçbir şey) ile eşleşebilir. (Not - geçerli bir Windows adı ile bitemez {space})

  • *.sonunda - herhangi 0 veya daha fazla karakter eşleşir hariç . sonlandıran .aslında herhangi bir kombinasyonu olabilir .ve {space}sürece maskeli en son karakter olarak . bu ilk ve tek istisnası *sadece herhangi bir karakter grubuyla eşleşmiyor.

Yukarıdaki kurallar o kadar da karmaşık değil. Ancak durumu kafa karıştırıcı yapan çok önemli bir kural daha var: sourceMask hem uzun hem de kısa 8.3 isimleriyle (eğer varsa) karşılaştırılır. Bu son kural, sonuçların yorumlanmasını çok zorlaştırabilir, çünkü maskenin kısa adla eşleşmesi her zaman açık değildir.

NTFS birimlerinde kısa 8.3 ad oluşturmayı devre dışı bırakmak için RegEdit kullanmak mümkündür; bu noktada dosya maskesi sonuçlarının yorumlanması çok daha ileri düzeydedir. Kısa isimleri devre dışı bırakmadan önce oluşturulan kısa isimler kalacaktır.

targetMask

Not - Çok sıkı bir test yapmadım, ancak aynı kuralların COPY komutunun hedef adı için de geçerli olduğu anlaşılıyor.

TargetMask yeni adı belirtir. Her zaman tam uzun isme uygulanır; TargetMask, sourceMask kısa 8.3 ismine uysa bile, hiçbir zaman kısa 8.3 ismine uygulanmaz.

SourceMask'ta bulunan joker karakterlerin varlığı veya yokluğu, joker karakterlerin targetMask'ta nasıl işlendiğini etkilemez.

Aşağıdaki tartışmada - cherhangi bir karakter temsil etmesidir değil *, ?ya da.

TargetMask, kaynak ismine karşı kesinlikle soldan sağa, geri izleme olmaksızın işlenir.

  • c- Bir sonraki karakter olmadığı .ve chedef adına eklendiği sürece kaynak ad içindeki konumu ilerletir . (Kaynaktaki karakteri değiştirir c, ancak hiçbir zaman değiştirmez .)

  • ?- Kaynak uzun ismin bir sonraki karakteriyle eşleşir ve bir sonraki karakter olmadığı sürece hedef ismine eklenir. . Bir sonraki karakter .varsa veya kaynak adın sonundaysa sonuç ve geçerli karaktere hiçbir karakter eklenmez. kaynak adındaki konum değişmedi.

  • *targetMask sonundaki - Kalan tüm karakterleri kaynaktan hedefe ekler. Zaten kaynak sonunda ise, o zaman hiçbir şey yapmaz.

  • *c- Tüm kaynak karakterleri geçerli konumdan son cdurumuna (büyük / küçük harfe duyarlı açgözlü eşleşme) kadar eşleştirir ve eşleşen karakter kümesini hedef adına ekler. Eğer cbulunmazsa tarafından, daha sonra kaynağından kalan bütün karakterler, eklenen takip edilmekte c Bu benim Windows dosya desen eşleştirme küçük harf duyarlı olduğu farkındayım tek durumdur.

  • *.- Tüm kaynak karakterleri geçerli konumdan son açılımına .(açgözlü eşleşme) kadar eşleştirir ve eşleşen karakter kümesini hedef adına ekler. Eğer .bulunmazsa, o zaman kaynağından kalan bütün karakterler eklenmiş izlemektedir.

  • *?- Kalan tüm karakterleri kaynaktan hedefe ekler. Zaten kaynak sonunda ise o zaman hiçbir şey yapmaz.

  • .*Önde olmadan - Herhangi bir karakter kopyalamadan ilk oluşumu gerçekleştirerek kaynaktaki konumunu yükseltir ve hedef adına .eklenir .. Eğer .kaynakta bulunmazsa, o zaman kaynağının sona ulaşana ve ekler .hedef adının.

TargetMask yorulduktan sonra, izlenen herhangi bir iz .ve {space}sonuçta elde edilen hedef adının sonunda kesilir, çünkü Windows dosya adları .veya{space}

Bazı pratik örnekler

Herhangi bir uzantıdan önce 1. ve 3. konumlardaki bir karakteri değiştirin (henüz mevcut değilse, 2. veya 3. karakteri ekler)

ren  *  A?Z*
  1        -> AZ
  12       -> A2Z
  1.txt    -> AZ.txt
  12.txt   -> A2Z.txt
  123      -> A2Z
  123.txt  -> A2Z.txt
  1234     -> A2Z4
  1234.txt -> A2Z4.txt

Her dosyanın (final) uzantısını değiştirin

ren  *  *.txt
  a     -> a.txt
  b.dat -> b.txt
  c.x.y -> c.x.txt

Her dosyaya bir eklenti ekle

ren  *  *?.bak
  a     -> a.bak
  b.dat -> b.dat.bak
  c.x.y -> c.x.y.bak

İlk uzantıdan sonra kalan tüm uzantıları kaldırın. ?Mevcut tam adı ve ilk uzantıyı korumak için yeterli kullanılması gerektiğini unutmayın .

ren  *  ?????.?????
  a     -> a
  a.b   -> a.b
  a.b.c -> a.b
  part1.part2.part3    -> part1.part2
  123456.123456.123456 -> 12345.12345   (note truncated name and extension because not enough `?` were used)

Yukarıdakiyle aynıdır, ancak 5 karakterden daha uzun bir ad ve / veya uzantıya sahip dosyaları kesilmeleri için filtreleyin. (Açıkça, ?6 karaktere kadar ad ve uzantıları korumak için targetMask'ın her iki ucuna da ek bir değer ekleyebilir )

ren  ?????.?????.*  ?????.?????
  a      ->  a
  a.b    ->  a.b
  a.b.c  ->  a.b
  part1.part2.part3  ->  part1.part2
  123456.123456.123456  (Not renamed because doesn't match sourceMask)

Soyadından sonra karakterleri değiştir _ve uzantıyı korumaya çalış. (Uzantıda _görünüyorsa düzgün çalışmıyor )

ren  *_*  *_NEW.*
  abcd_12345.txt  ->  abcd_NEW.txt
  abc_newt_1.dat  ->  abc_newt_NEW.dat
  abcdef.jpg          (Not renamed because doesn't match sourceMask)
  abcd_123.a_b    ->  abcd_123.a_NEW  (not desired, but no simple RENAME form will work in this case)

Herhangi bir ad, . Karakterler tarafından sınırlandırılmış bileşenlere ayrılabilir , ancak her bileşenin sonuna eklenebilir veya silinebilir. Kalan karakterleri joker karakterlerle korurken, bir bileşenin başına veya ortasına karakterler silinemez veya eklenemez. Yerine herhangi bir yerde değişiklik yapılabilir.

ren  ??????.??????.??????  ?x.????999.*rForTheCourse
  part1.part2            ->  px.part999.rForTheCourse
  part1.part2.part3      ->  px.part999.parForTheCourse
  part1.part2.part3.part4   (Not renamed because doesn't match sourceMask)
  a.b.c                  ->  ax.b999.crForTheCourse
  a.b.CarPart3BEER       ->  ax.b999.CarParForTheCourse

Kısa isimler etkinleştirilirse, isim için en az 8 , uzantı için ?en az 3 ?olan bir sourceMask tüm dosyalar ile eşleşecektir çünkü daima kısa 8.3 adı ile eşleşecektir.

ren ????????.???  ?x.????999.*rForTheCourse
  part1.part2.part3.part4  ->  px.part999.part3.parForTheCourse


Faydalı tuhaflık / böcek? ad öneklerini silmek için

Bu SuperUser gönderisi , /baş karakterleri bir dosya adından silmek için bir dizi eğik çizginin ( ) nasıl kullanılabileceğini açıklar . Silinecek her karakter için bir eğik çizgi gerekir. Bir Windows 10 makinesindeki davranışı onayladım.

ren "abc-*.txt" "////*.txt"
  abc-123.txt        --> 123.txt
  abc-HelloWorld.txt --> HelloWorld.txt

Bu teknik yalnızca hem kaynak hem de hedef maskeleri çift tırnak içine alınmışsa çalışır. Gerekli alıntılar olmadan aşağıdaki formların tümü bu hatayla başarısız olur:The syntax of the command is incorrect

REM - All of these forms fail with a syntax error.
ren abc-*.txt "////*.txt"
ren "abc-*.txt" ////*.txt
ren abc-*.txt ////*.txt

/Bir dosya adı ortasında veya sonunda herhangi karakterleri kaldırmak için kullanılamaz. Yalnızca baştaki (önek) karakterleri kaldırabilir.

Teknik /olarak bir joker olarak çalışmaz. Aksine basit bir karakter değiştirme işlemi gerçekleştirir, ancak değiştirme işleminden sonra, REN komutu bunun /bir dosya adında geçerli olmadığını kabul eder ve /baştaki eğik çizgileri addan çıkarır. REN, /hedef adın ortasında tespit ederse sözdizimi hatası verir .


Olası RENAME hatası - tek bir komut aynı dosyayı iki kez yeniden adlandırabilir!

Boş bir test klasörüne başlamak:

C:\test>copy nul 123456789.123
        1 file(s) copied.

C:\test>dir /x
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of C:\test

09/15/2012  07:42 PM    <DIR>                       .
09/15/2012  07:42 PM    <DIR>                       ..
09/15/2012  07:42 PM                 0 123456~1.123 123456789.123
               1 File(s)              0 bytes
               2 Dir(s)  327,237,562,368 bytes free

C:\test>ren *1* 2*3.?x

C:\test>dir /x
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of C:\test

09/15/2012  07:42 PM    <DIR>                       .
09/15/2012  07:42 PM    <DIR>                       ..
09/15/2012  07:42 PM                 0 223456~1.XX  223456789.123.xx
               1 File(s)              0 bytes
               2 Dir(s)  327,237,562,368 bytes free

REM Expected result = 223456789.123.x

SourceMask *1*dosyasının ilk önce uzun dosya adıyla eşleştiğine ve dosyanın beklenen sonuç olarak yeniden adlandırıldığına inanıyorum 223456789.123.x. RENAME daha sonra işlenecek daha fazla dosya aramaya devam eder ve yeni adlandırılmış dosyayı yeni kısa adıyla bulur 223456~1.X. Daha sonra dosya nihai sonucunu vererek yeniden adlandırılır 223456789.123.xx.

8.3 ad üretimini devre dışı bırakırsam, RENAME beklenen sonucu verir.

Bu tuhaf davranışı tetiklemek için mevcut olması gereken tüm tetikleyici koşulları tam olarak çözmedim. Hiç bitmeyen bir özyinelemeli RENAME yaratmanın mümkün olabileceğinden endişe duydum, ancak hiçbir zaman birisini teşvik edemedim.

Hatayı uyarmak için aşağıdakilerin hepsinin doğru olması gerektiğine inanıyorum. Gördüğüm her hatalı vaka aşağıdaki koşullara sahipti, ancak aşağıdaki koşulları sağlayan tüm vakalar tıkanmadı.

  • Kısa 8.3 isim etkin olmalı
  • SourceMask, orijinal uzun adla eşleşmelidir.
  • İlk yeniden adlandırma, sourceMask ile de eşleşen kısa bir ad oluşturmalıdır.
  • İlk yeniden adlandırılan kısa ad, orijinal kısa addan sonra sıralanmalıdır (varsa?)

6
Ne kadar kapsamlı bir cevap .. +1.
meder omuraliev

İnanılmaz derecede ayrıntılı!
Andriy M

13
Buna dayanarak, Microsoft sadece "Kullanım için, bkz. Superuser.com/a/475875 " eklemesi gerekir REN /?.
efotinis

4
@CAD - Bu cevap Simon'ın isteğim üzerine kendi sitesinde eklediği% 100 orijinal içeriktir. Şu SS64 sayfasının en altına bak, Simon'un bana iş için kredi verdiğini göreceksin.
dbenham

2
@ JacksOnF1re - Cevabıma yeni bilgi / teknik eklendi. Gerçekten Copy of öneklerinizi belirsiz bir eğik çizgi tekniği kullanarak silebilirsiniz :ren "Copy of *.txt" "////////*"
dbenham

4

Exebook'a benzer şekilde, burada bir kaynak dosyadan hedef dosya adını almak için C # uygulamasıdır.

Dbenham'ın örneklerinde 1 küçük hata buldum:

 ren  *_*  *_NEW.*
   abc_newt_1.dat  ->  abc_newt_NEW.txt (should be: abd_newt_NEW.dat)

İşte kod:

    /// <summary>
    /// Returns a filename based on the sourcefile and the targetMask, as used in the second argument in rename/copy operations.
    /// targetMask may contain wildcards (* and ?).
    /// 
    /// This follows the rules of: http://superuser.com/questions/475874/how-does-the-windows-rename-command-interpret-wildcards
    /// </summary>
    /// <param name="sourcefile">filename to change to target without wildcards</param>
    /// <param name="targetMask">mask with wildcards</param>
    /// <returns>a valid target filename given sourcefile and targetMask</returns>
    public static string GetTargetFileName(string sourcefile, string targetMask)
    {
        if (string.IsNullOrEmpty(sourcefile))
            throw new ArgumentNullException("sourcefile");

        if (string.IsNullOrEmpty(targetMask))
            throw new ArgumentNullException("targetMask");

        if (sourcefile.Contains('*') || sourcefile.Contains('?'))
            throw new ArgumentException("sourcefile cannot contain wildcards");

        // no wildcards: return complete mask as file
        if (!targetMask.Contains('*') && !targetMask.Contains('?'))
            return targetMask;

        var maskReader = new StringReader(targetMask);
        var sourceReader = new StringReader(sourcefile);
        var targetBuilder = new StringBuilder();


        while (maskReader.Peek() != -1)
        {

            int current = maskReader.Read();
            int sourcePeek = sourceReader.Peek();
            switch (current)
            {
                case '*':
                    int next = maskReader.Read();
                    switch (next)
                    {
                        case -1:
                        case '?':
                            // Append all remaining characters from sourcefile
                            targetBuilder.Append(sourceReader.ReadToEnd());
                            break;
                        default:
                            // Read source until the last occurrance of 'next'.
                            // We cannot seek in the StringReader, so we will create a new StringReader if needed
                            string sourceTail = sourceReader.ReadToEnd();
                            int lastIndexOf = sourceTail.LastIndexOf((char) next);
                            // If not found, append everything and the 'next' char
                            if (lastIndexOf == -1)
                            {
                                targetBuilder.Append(sourceTail);
                                targetBuilder.Append((char) next);

                            }
                            else
                            {
                                string toAppend = sourceTail.Substring(0, lastIndexOf + 1);
                                string rest = sourceTail.Substring(lastIndexOf + 1);
                                sourceReader.Dispose();
                                // go on with the rest...
                                sourceReader = new StringReader(rest);
                                targetBuilder.Append(toAppend);
                            }
                            break;
                    }

                    break;
                case '?':
                    if (sourcePeek != -1 && sourcePeek != '.')
                    {
                        targetBuilder.Append((char)sourceReader.Read());
                    }
                    break;
                case '.':
                    // eat all characters until the dot is found
                    while (sourcePeek != -1 && sourcePeek != '.')
                    {
                        sourceReader.Read();
                        sourcePeek = sourceReader.Peek();
                    }

                    targetBuilder.Append('.');
                    // need to eat the . when we peeked it
                    if (sourcePeek == '.')
                        sourceReader.Read();

                    break;
                default:
                    if (sourcePeek != '.') sourceReader.Read(); // also consume the source's char if not .
                    targetBuilder.Append((char)current);
                    break;
            }

        }

        sourceReader.Dispose();
        maskReader.Dispose();
        return targetBuilder.ToString().TrimEnd('.', ' ');
    }

Ve burada örnekleri test etmek için bir NUnit test yöntemi:

    [Test]
    public void TestGetTargetFileName()
    {
        string targetMask = "?????.?????";
        Assert.AreEqual("a", FileUtil.GetTargetFileName("a", targetMask));
        Assert.AreEqual("a.b", FileUtil.GetTargetFileName("a.b", targetMask));
        Assert.AreEqual("a.b", FileUtil.GetTargetFileName("a.b.c", targetMask));
        Assert.AreEqual("part1.part2", FileUtil.GetTargetFileName("part1.part2.part3", targetMask));
        Assert.AreEqual("12345.12345", FileUtil.GetTargetFileName("123456.123456.123456", targetMask));

        targetMask = "A?Z*";
        Assert.AreEqual("AZ", FileUtil.GetTargetFileName("1", targetMask));
        Assert.AreEqual("A2Z", FileUtil.GetTargetFileName("12", targetMask));
        Assert.AreEqual("AZ.txt", FileUtil.GetTargetFileName("1.txt", targetMask));
        Assert.AreEqual("A2Z.txt", FileUtil.GetTargetFileName("12.txt", targetMask));
        Assert.AreEqual("A2Z", FileUtil.GetTargetFileName("123", targetMask));
        Assert.AreEqual("A2Z.txt", FileUtil.GetTargetFileName("123.txt", targetMask));
        Assert.AreEqual("A2Z4", FileUtil.GetTargetFileName("1234", targetMask));
        Assert.AreEqual("A2Z4.txt", FileUtil.GetTargetFileName("1234.txt", targetMask));

        targetMask = "*.txt";
        Assert.AreEqual("a.txt", FileUtil.GetTargetFileName("a", targetMask));
        Assert.AreEqual("b.txt", FileUtil.GetTargetFileName("b.dat", targetMask));
        Assert.AreEqual("c.x.txt", FileUtil.GetTargetFileName("c.x.y", targetMask));

        targetMask = "*?.bak";
        Assert.AreEqual("a.bak", FileUtil.GetTargetFileName("a", targetMask));
        Assert.AreEqual("b.dat.bak", FileUtil.GetTargetFileName("b.dat", targetMask));
        Assert.AreEqual("c.x.y.bak", FileUtil.GetTargetFileName("c.x.y", targetMask));

        targetMask = "*_NEW.*";
        Assert.AreEqual("abcd_NEW.txt", FileUtil.GetTargetFileName("abcd_12345.txt", targetMask));
        Assert.AreEqual("abc_newt_NEW.dat", FileUtil.GetTargetFileName("abc_newt_1.dat", targetMask));
        Assert.AreEqual("abcd_123.a_NEW", FileUtil.GetTargetFileName("abcd_123.a_b", targetMask));

        targetMask = "?x.????999.*rForTheCourse";

        Assert.AreEqual("px.part999.rForTheCourse", FileUtil.GetTargetFileName("part1.part2", targetMask));
        Assert.AreEqual("px.part999.parForTheCourse", FileUtil.GetTargetFileName("part1.part2.part3", targetMask));
        Assert.AreEqual("ax.b999.crForTheCourse", FileUtil.GetTargetFileName("a.b.c", targetMask));
        Assert.AreEqual("ax.b999.CarParForTheCourse", FileUtil.GetTargetFileName("a.b.CarPart3BEER", targetMask));

    }

Kafamdaki örneğimdeki hata için teşekkürler. Düzeltmek için cevabımı düzenledim.
dbenham

1

Belki birileri bunu faydalı bulabilir. Bu JavaScript kodu, yukarıdaki dbenham tarafından verilen cevaba dayanmaktadır.

sourceMaskÇok fazla test etmedim , ancak targetMaskdbenham tarafından verilen tüm örneklerle eşleşmiyor.

function maskMatch(path, mask) {
    mask = mask.replace(/\./g, '\\.')
    mask = mask.replace(/\?/g, '.')
    mask = mask.replace(/\*/g, '.+?')
    var r = new RegExp('^'+mask+'$', '')
    return path.match(r)
}

function maskNewName(path, mask) {
    if (path == '') return
    var x = 0, R = ''
    for (var m = 0; m < mask.length; m++) {
        var ch = mask[m], q = path[x], z = mask[m + 1]
        if (ch != '.' && ch != '*' && ch != '?') {
            if (q && q != '.') x++
            R += ch
        } else if (ch == '?') {
            if (q && q != '.') R += q, x++
        } else if (ch == '*' && m == mask.length - 1) {
            while (x < path.length) R += path[x++]
        } else if (ch == '*') {
            if (z == '.') {
                for (var i = path.length - 1; i >= 0; i--) if (path[i] == '.') break
                if (i < 0) {
                    R += path.substr(x, path.length) + '.'
                    i = path.length
                } else R += path.substr(x, i - x + 1)
                x = i + 1, m++
            } else if (z == '?') {
                R += path.substr(x, path.length), m++, x = path.length
            } else {
                for (var i = path.length - 1; i >= 0; i--) if (path[i] == z) break
                if (i < 0) R += path.substr(x, path.length) + z, x = path.length, m++
                else R += path.substr(x, i - x), x = i + 1
            }
        } else if (ch == '.') {
            while (x < path.length) if (path[x++] == '.') break
            R += '.'
        }
    }
    while (R[R.length - 1] == '.') R = R.substr(0, R.length - 1)
}

0

Joker karakter dosya adlarını maskelemek için bu kodu BASIC dilinde yazmayı başardım:

REM inputs a filename and matches wildcards returning masked output filename.
FUNCTION maskNewName$ (path$, mask$)
IF path$ = "" THEN EXIT FUNCTION
IF INSTR(path$, "?") OR INSTR(path$, "*") THEN EXIT FUNCTION
x = 0
R$ = ""
FOR m = 0 TO LEN(mask$) - 1
    ch$ = MID$(mask$, m + 1, 1)
    q$ = MID$(path$, x + 1, 1)
    z$ = MID$(mask$, m + 2, 1)
    IF ch$ <> "." AND ch$ <> "*" AND ch$ <> "?" THEN
        IF LEN(q$) AND q$ <> "." THEN x = x + 1
        R$ = R$ + ch$
    ELSE
        IF ch$ = "?" THEN
            IF LEN(q$) AND q$ <> "." THEN R$ = R$ + q$: x = x + 1
        ELSE
            IF ch$ = "*" AND m = LEN(mask$) - 1 THEN
                WHILE x < LEN(path$)
                    R$ = R$ + MID$(path$, x + 1, 1)
                    x = x + 1
                WEND
            ELSE
                IF ch$ = "*" THEN
                    IF z$ = "." THEN
                        FOR i = LEN(path$) - 1 TO 0 STEP -1
                            IF MID$(path$, i + 1, 1) = "." THEN EXIT FOR
                        NEXT
                        IF i < 0 THEN
                            R$ = R$ + MID$(path$, x + 1) + "."
                            i = LEN(path$)
                        ELSE
                            R$ = R$ + MID$(path$, x + 1, i - x + 1)
                        END IF
                        x = i + 1
                        m = m + 1
                    ELSE
                        IF z$ = "?" THEN
                            R$ = R$ + MID$(path$, x + 1, LEN(path$))
                            m = m + 1
                            x = LEN(path$)
                        ELSE
                            FOR i = LEN(path$) - 1 TO 0 STEP -1
                                'IF MID$(path$, i + 1, 1) = z$ THEN EXIT FOR
                                IF UCASE$(MID$(path$, i + 1, 1)) = UCASE$(z$) THEN EXIT FOR
                            NEXT
                            IF i < 0 THEN
                                R$ = R$ + MID$(path$, x + 1, LEN(path$)) + z$
                                x = LEN(path$)
                                m = m + 1
                            ELSE
                                R$ = R$ + MID$(path$, x + 1, i - x)
                                x = i + 1
                            END IF
                        END IF
                    END IF
                ELSE
                    IF ch$ = "." THEN
                        DO WHILE x < LEN(path$)
                            IF MID$(path$, x + 1, 1) = "." THEN
                                x = x + 1
                                EXIT DO
                            END IF
                            x = x + 1
                        LOOP
                        R$ = R$ + "."
                    END IF
                END IF
            END IF
        END IF
    END IF
NEXT
DO WHILE RIGHT$(R$, 1) = "."
    R$ = LEFT$(R$, LEN(R$) - 1)
LOOP
R$ = RTRIM$(R$)
maskNewName$ = R$
END FUNCTION

4
Bu soruda sorulanın nasıl cevaplandığını netleştirir misiniz?
fixer1234 13:16

REN, dosya adlarını yeniden adlandırmadan önce işlevin nasıl çağrıldığına bağlı olarak REN * .TMP * .DOC işleme gibi joker karakter eşleşmesi için kullandığı işlevi çoğaltır.
eoredson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.